aliceblue11 commited on
Commit
7e9dab8
·
verified ·
1 Parent(s): 654a143

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +753 -1
app.py CHANGED
@@ -131,4 +131,756 @@ class ConceptAnalyzer:
131
  trends = data.get("trends", [])
132
  female_appeal = data.get("female_appeal", [])
133
 
134
- for i in range(min(10, len
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
  trends = data.get("trends", [])
132
  female_appeal = data.get("female_appeal", [])
133
 
134
+ for i in range(min(10, len(special_days) + len(trends))):
135
+ if i < len(special_days):
136
+ concept_name = f"{special_days[i]} 이벤트"
137
+ theme = f"{special_days[i]}를 테마로 한 참여형 이벤트"
138
+ keywords = [special_days[i]] + female_appeal[:2]
139
+ score = 8.8 - (i * 0.1)
140
+ is_recommended = i < 3
141
+ else:
142
+ trend_idx = i - len(special_days)
143
+ if trend_idx < len(trends):
144
+ trend = trends[trend_idx]
145
+ concept_name = f"{trend} 챌린지"
146
+ theme = f"{trend} 참여형 챌린지 이벤트"
147
+ keywords = [trend] + trends[trend_idx+1:trend_idx+3]
148
+ score = 8.0 - (trend_idx * 0.1)
149
+ is_recommended = trend_idx < 2
150
+ else:
151
+ break
152
+
153
+ concepts.append({
154
+ "name": concept_name,
155
+ "theme": theme,
156
+ "score": round(score, 1),
157
+ "reason": f"20-40대 여성에게 인기 높은 {concept_name.split()[0]} 테마",
158
+ "target": "20-40대 여성",
159
+ "colors": data.get("colors", ["#FF69B4"]),
160
+ "keywords": keywords,
161
+ "is_recommended": is_recommended
162
+ })
163
+
164
+ concepts.sort(key=lambda x: (x.get("is_recommended", False), x["score"]), reverse=True)
165
+
166
+ recommended_concept = next((c for c in concepts if c.get("is_recommended", False)), concepts[0])
167
+
168
+ result = f"# 🎯 {month} 20-40대 여성 맞춤 컨셉 분석\n\n"
169
+ result += f"## 🏆 이달의 추천 컨셉: {recommended_concept['name']}\n"
170
+ result += f"**⭐ 추천 이유:** {recommended_concept['reason']}\n"
171
+ result += f"**📊 예상 참여도:** {recommended_concept['score']}/10점\n\n"
172
+ result += "---\n\n"
173
+
174
+ concept_names = []
175
+
176
+ for i, concept in enumerate(concepts, 1):
177
+ is_recommended_mark = " 🏆 **추천**" if concept.get("is_recommended", False) else ""
178
+ result += f"## {i}. {concept['name']}{is_recommended_mark}\n"
179
+ result += f"**🏷️ 테마:** {concept['theme']}\n"
180
+ result += f"**⭐ 참여도 점수:** {concept['score']}/10점\n"
181
+ result += f"**💡 선정 이유:** {concept['reason']}\n"
182
+ result += f"**🎯 주요 타겟:** {concept['target']}\n"
183
+ result += f"**🔑 핵심 키워드:** {', '.join(concept['keywords'])}\n"
184
+ result += f"**🎨 추천 색상:** {', '.join(concept['colors'])}\n\n"
185
+ result += "---\n\n"
186
+
187
+ concept_names.append(concept['name'])
188
+
189
+ return result, concept_names
190
+
191
+ def generate_trendy_copy(self, concept_name, month):
192
+ """트렌디한 카피라이팅 생성"""
193
+
194
+ trendy_copies = {
195
+ "미니멀": {
196
+ "sub1": "🌟 '나는 정리를 못하는 여자'는 이제 그만!",
197
+ "main": "미니멀은 '미'니로 '말'하는 거야, 작게 말해도 큰 변화! ✨",
198
+ "sub2": "올해는 진짜 '갓생'을 살아보자구요! 💪",
199
+ "hashtags": ["#갓생살기", "#미니멀", "#정리의신", "#새해정리"]
200
+ },
201
+ "셀프케어": {
202
+ "sub1": "💕 '나 자신과 연애 중'이라고 말할 수 있나요?",
203
+ "main": "셀프케어는 '셀프'로 '케어'하는 거 맞아! 💖",
204
+ "sub2": "오늘부터 내가 내 최고의 친구가 되는 거야 ✨",
205
+ "hashtags": ["#셀프케어", "#나를위한시간", "#힐링", "#자기사랑"]
206
+ },
207
+ "갓생": {
208
+ "sub1": "✨ 매일 똑같은 하루가 지겨우신가요?",
209
+ "main": "갓생은 '갓'처럼 살아보자는 거야! 너도 할 수 있어 🔥",
210
+ "sub2": "작은 변화가 큰 행복을 만들어요 💫",
211
+ "hashtags": ["#갓생살기", "#미라클모닝", "#자기계발", "#루틴만들기"]
212
+ },
213
+ "챌린지": {
214
+ "sub1": "🎯 혼자서는 어려워도 함께라면 가능해!",
215
+ "main": "챌린지는 '챌'만 해봐도 성공이야! 도전해볼까? 🚀",
216
+ "sub2": "우리 함께 새로운 나를 만나러 가요 ✨",
217
+ "hashtags": ["#챌린지", "#함께해요", "#새로운나", "#도전"]
218
+ },
219
+ "벚꽃": {
220
+ "sub1": "🌸 봄이 왔어요! 설레는 마음 준비되셨나요?",
221
+ "main": "벚꽃은 '벚'보다 '꽃'이 중요해! 꽃처럼 예쁘게 피어나요 🌺",
222
+ "sub2": "짧지만 아름다��� 순간을 함께 만들어요 💕",
223
+ "hashtags": ["#벚꽃놀이", "#봄나들이", "#꽃구경", "#봄감성"]
224
+ },
225
+ "바캉스": {
226
+ "sub1": "🏖️ 더위는 싫어도 여름은 좋아하는 사람?",
227
+ "main": "바캉스는 '바'쁜 일상에서 '캉'스럽게 쉬는 거야! 🌊",
228
+ "sub2": "올여름 가장 핫한 추억을 만들어봐요 🔥",
229
+ "hashtags": ["#바캉스", "#여름휴가", "#힐링여행", "#여름추억"]
230
+ },
231
+ "카페": {
232
+ "sub1": "☕ 오늘도 카페인에 의존하며 살고 계신가요?",
233
+ "main": "카페는 '카'페인보다 '페'이스북 같은 소통공간! 📸",
234
+ "sub2": "따뜻한 커피 한 잔으로 시작하는 특별한 하루 ✨",
235
+ "hashtags": ["#카페투어", "#커피타임", "#감성카페", "#카페추천"]
236
+ },
237
+ "크리스마스": {
238
+ "sub1": "🎄 올해 크리스마스는 뭔가 특별하게 보내고 싶다면?",
239
+ "main": "크리스마스는 '크'게 '리'액션하며 '스'페셜하게! 🎅",
240
+ "sub2": "따뜻한 마음이 가득한 연말을 함께 만들어요 💝",
241
+ "hashtags": ["#크리스마스", "#연말파티", "#선물", "#따뜻한연말"]
242
+ }
243
+ }
244
+
245
+ # 기본 카피
246
+ default_copy = {
247
+ "sub1": "✨ 이런 특별한 순간을 놓칠 수 없죠!",
248
+ "main": "지금 이 순간이 바로 '찐'이야! 💫",
249
+ "sub2": "함께라면 뭐든 '레전드'가 될 수 있어요 🎉",
250
+ "hashtags": ["#찐이야", "#레전드순간", "#함께해요", "#특별한시간"]
251
+ }
252
+
253
+ # 컨셉명에서 키워드 찾기
254
+ for keyword, copy_data in trendy_copies.items():
255
+ if keyword in concept_name:
256
+ return copy_data
257
+
258
+ return default_copy
259
+
260
+ # ================== 이벤트 관리 모듈 ==================
261
+ class EventManager:
262
+ def __init__(self):
263
+ self.reward_types = [
264
+ "네이버페이 금액권",
265
+ "배달의민족 상품권",
266
+ "스타벅스 기프트카드",
267
+ "CGV 영화관람권",
268
+ "올리브영 상품권"
269
+ ]
270
+
271
+ def calculate_event_duration(self, start_date, end_date):
272
+ try:
273
+ start = datetime.strptime(start_date, "%Y-%m-%d")
274
+ end = datetime.strptime(end_date, "%Y-%m-%d")
275
+ duration = (end - start).days + 1
276
+ month = start.month
277
+
278
+ start_weekday = start.strftime("(%a)")
279
+ end_weekday = end.strftime("(%a)")
280
+
281
+ return duration, month, start_weekday, end_weekday, start, end
282
+ except:
283
+ return 0, 0, "", "", None, None
284
+
285
+ def generate_detailed_comment_event(self, start_date, end_date, concept, reward_structure, kakao_id, phone_number):
286
+ if not concept:
287
+ return "먼저 이벤트 컨셉을 입력해주세요."
288
+
289
+ duration_info, month, start_weekday, end_weekday, start_dt, end_dt = self.calculate_event_duration(start_date, end_date)
290
+
291
+ if duration_info == 0:
292
+ return "날짜 형식을 확인해주세요."
293
+
294
+ formatted_start = f"{start_dt.year}년 {start_dt.month}월 {start_dt.day}일 {start_weekday} 00:00"
295
+ formatted_end = f"{end_dt.year}년 {end_dt.month}월 {end_dt.day}일 {end_weekday} 23:59"
296
+
297
+ template = f"""댓글 남기면 1시간마다 선물이!
298
+ 🎉 {concept} 이벤트
299
+
300
+ {formatted_start} - {formatted_end} ({duration_info}일간)
301
+
302
+ ========================
303
+ EVENT
304
+ <커뮤니티>에 작성된 글에 유익하고 착한 댓글을 남기면
305
+ 1시간마다 1명씩! 하루 24명에게 선물을드려요!
306
+
307
+ {formatted_start} - {formatted_end} ({duration_info}일간)
308
+
309
+ =====================
310
+ STEP 1
311
+ 회사명 <커뮤니티>에 작성된 글에
312
+ 유익하고 착한 댓글 작성
313
+ * 이쁘고 좋은 말 많이 해주는 회원님들이 되길 부탁드려요
314
+
315
+ STEP 2
316
+ 댓글 작성 후 선물 당첨 팝업이 나타나면
317
+ 화면캡쳐 또는 사진촬영하기!
318
+ *당첨팝업은 이벤트 기간동안 1시간마다 1명씩!
319
+ 하루 24명에게 나타나요!
320
+
321
+ STEP 3
322
+ 당첨팝업 캡쳐 & 촬영했으면
323
+ 카카오톡 또는 고객센터로 연락하기!
324
+
325
+ =================
326
+ 당첨혜택
327
+ {reward_structure}
328
+
329
+ ========================
330
+ 이벤트 대상
331
+ 일반 여성회원이라면 누구나!
332
+ (*회원, 비회원 모두 참여가능 / 기업회원제외)
333
+
334
+ ========================
335
+ 수령방법
336
+ 댓글 작성 후 랜덤하게뜨는 이미지를 캡처 or 사진 촬영하기!
337
+ 꼭 캡처후 팝업을 닫아주세요!
338
+
339
+ 1.상단 당첨 날짜와 시간이 함께 나오도록
340
+ 화면캡쳐 또는 사진촬영
341
+
342
+ 2.카카오톡 ({kakao_id}) 로 캡쳐 사진 보내기
343
+
344
+ 3.카카오톡으로 연락처를 남기거나
345
+ 고객센터 운영시간에 맞춰 전화하기
346
+
347
+ 4. 고객센터와 여성회원 확인 통화 후
348
+ 선물 받기!
349
+
350
+ =========================
351
+ 꼭 확인하세요!
352
+ ※본이벤트는 회사명 일반 여성회원만 참여가능합니다. (비회원도 가능)
353
+ ※ pc에서 캡처가 어려운 경우, 카메라로 촬영하여 연락 주셔도 됩니다.
354
+ ※이벤트 팝업 상품 이미지와 상단 당첨 날짜&시간을 함께
355
+ 화면 캡처 또는 사진 촬영해야 수령 가능합니다.
356
+ ※ 화면 캡처 전에 팝업을 닫을 시, 상품 지급이 어려우니 반드시 캡처 또는
357
+ 촬영 후 팝업을 닫아주세요!
358
+ ※당첨 시 여성확인절차가 있음으로 고객센터로 연락 주시기 바랍니다. (통화로 여성확인)
359
+ ※ 고객센터와 여성 확인 통화 후 상품 수령가능합니다.
360
+ ※ 상품은 1인 1일 최대 1회까지 수령이 가능합니다. 같은 날 재당첨되어도
361
+ 지급되지 않습니다. 단, 날짜가 다를 시 중복 수령 가능합니다.
362
+ ※ 상품 수령 가능 기간은 당첨 일로부터 영업일 기준 다음 날까지 가능합니다.
363
+ ex) 주말 당첨시, 고객센터 영업일(월) 업무 종료시간 19:00시까지 수령가능
364
+
365
+ ===========================
366
+ {phone_number}
367
+ ※ 대표번호는 문자수신이 불가합니다
368
+ 고객센터 운영시간
369
+ (평일 09:30~19:00 / 점심 12:00~13:30)
370
+ ※ 주말 및 공휴일은 운영하지 않습니다.
371
+ 카카오톡 ID: {kakao_id}
372
+ """
373
+
374
+ return template
375
+
376
+ def generate_design_advice(self, concept):
377
+ advice = f"""🎨 디자인 조언 ({concept} 테마)
378
+
379
+ 🎯 컬러 팔레트
380
+ - 20-40대 여성에게 어필하는 따뜻하고 친근한 색상
381
+ - 메인 컬러: 브랜드 컬러와 조화
382
+ - 서브 컬러: 가독성을 높이는 대비 색상
383
+
384
+ 📐 레이아웃 구조
385
+ 1. **메인 제목**: 임팩트 있는 큰 폰트 + 이모티콘
386
+ 2. **날짜 정보**: 박스로 구분하여 명확하게 표시
387
+ 3. **EVENT 섹션**: 굵은 구분선으로 강조
388
+ 4. **STEP 가이드**: 숫자와 함께 단계별 명확한 구분
389
+ 5. **당첨혜택**: 상품 이미지와 함께 시각적으로 강조
390
+ 6. **주의사항**: 읽기 쉽게 ※ 기호로 구분
391
+
392
+ 👀 가독성 향상 포인트
393
+ - 구분선(=====) 활용으로 섹션 명확히 분리
394
+ - 중요 정보는 박스 처리 또는 배경색 변경
395
+ - 단계별 가이드는 아이콘과 함께 시각화
396
+ - 모바일에서도 스크롤하며 읽기 편하게 구성
397
+
398
+ 🔥 핵심 강조 요소
399
+ - "1시간마다 1명씩" - 긴급성 강조
400
+ - "하루 24명" - 기회의 많음 어필
401
+ - 상품 이미지 - 실제 혜택 시각화
402
+ - 참여 방법 - 간단함 강조"""
403
+
404
+ return advice
405
+
406
+ # ================== API 연동 모듈 ==================
407
+ class APIIntegrations:
408
+ def __init__(self):
409
+ self.api_status = {}
410
+
411
+ def test_instagram_api(self, access_token):
412
+ try:
413
+ if not access_token:
414
+ return {"status": "error", "message": "Access Token이 필요합니다"}
415
+
416
+ url = f"https://graph.instagram.com/me?fields=id,username&access_token={access_token}"
417
+ response = requests.get(url, timeout=10)
418
+
419
+ if response.status_code == 200:
420
+ data = response.json()
421
+ return {
422
+ "status": "success",
423
+ "message": f"Instagram 연결 성공 - @{data.get('username', 'unknown')}"
424
+ }
425
+ else:
426
+ return {"status": "error", "message": "Instagram API 인증 실패"}
427
+
428
+ except Exception as e:
429
+ return {"status": "error", "message": f"Instagram 연결 오류: {str(e)}"}
430
+
431
+ def test_analytics_api(self, tracking_id):
432
+ try:
433
+ if not tracking_id:
434
+ return {"status": "error", "message": "Tracking ID가 필요합니다"}
435
+
436
+ if tracking_id.startswith("G-"):
437
+ return {"status": "success", "message": f"Google Analytics 설정 확인됨 - {tracking_id}"}
438
+ else:
439
+ return {"status": "error", "message": "올바른 GA4 Tracking ID 형식이 아닙니다 (G-XXXXXXXXX)"}
440
+
441
+ except Exception as e:
442
+ return {"status": "error", "message": f"Analytics 연결 오류: {str(e)}"}
443
+
444
+ def test_openai_api(self, api_key):
445
+ try:
446
+ if not api_key:
447
+ return {"status": "error", "message": "API Key가 필요합니다"}
448
+
449
+ headers = {
450
+ "Authorization": f"Bearer {api_key}",
451
+ "Content-Type": "application/json"
452
+ }
453
+
454
+ url = "https://api.openai.com/v1/models"
455
+ response = requests.get(url, headers=headers, timeout=10)
456
+
457
+ if response.status_code == 200:
458
+ return {"status": "success", "message": "OpenAI API 연결 성공"}
459
+ else:
460
+ return {"status": "error", "message": "OpenAI API 인증 실패"}
461
+
462
+ except Exception as e:
463
+ return {"status": "error", "message": f"OpenAI API 연결 오류: {str(e)}"}
464
+
465
+ def test_all_connections(self, enable_instagram, instagram_token, enable_analytics, ga_tracking_id, enable_chatgpt, openai_api_key):
466
+ results = []
467
+ timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
468
+
469
+ results.append(f"🔍 API 연결 테스트 결과 - {timestamp}\n" + "="*50 + "\n")
470
+
471
+ if enable_instagram:
472
+ instagram_result = self.test_instagram_api(instagram_token)
473
+ status_icon = "✅" if instagram_result["status"] == "success" else "❌"
474
+ results.append(f"{status_icon} Instagram: {instagram_result['message']}")
475
+
476
+ if enable_analytics:
477
+ analytics_result = self.test_analytics_api(ga_tracking_id)
478
+ status_icon = "✅" if analytics_result["status"] == "success" else "❌"
479
+ results.append(f"{status_icon} Analytics: {analytics_result['message']}")
480
+
481
+ if enable_chatgpt:
482
+ openai_result = self.test_openai_api(openai_api_key)
483
+ status_icon = "✅" if openai_result["status"] == "success" else "❌"
484
+ results.append(f"{status_icon} OpenAI: {openai_result['message']}")
485
+
486
+ if len(results) == 1:
487
+ results.append("⚠️ 설정된 API가 없습니다. API를 활성화해주세요.")
488
+
489
+ return "\n".join(results)
490
+
491
+ def generate_enhanced_concept_with_chatgpt(self, month, api_key):
492
+ try:
493
+ headers = {
494
+ "Authorization": f"Bearer {api_key}",
495
+ "Content-Type": "application/json"
496
+ }
497
+
498
+ prompt = f"""
499
+ {month}에 진행할 20-40대 여성 대상 이벤트의 창의적인 컨셉을 3개 제안해주세요.
500
+ 각 컨셉은 다음을 포함해야 합니다:
501
+ - 컨셉명
502
+ - 핵심 아이디어
503
+ - 예상 참여도 (1-10점)
504
+ - 타겟층 특징
505
+ - 트렌디한 해시태그 3개
506
+ - 실행 방법
507
+
508
+ 현재 유행하는 소셜미디어 트렌드와 MZ세대 관심사를 반영해주세요.
509
+ 2024년 하반기 트렌드를 고려하여 답변해주세요.
510
+ """
511
+
512
+ data = {
513
+ "model": "gpt-3.5-turbo",
514
+ "messages": [
515
+ {"role": "user", "content": prompt}
516
+ ],
517
+ "max_tokens": 1500,
518
+ "temperature": 0.8
519
+ }
520
+
521
+ response = requests.post(
522
+ "https://api.openai.com/v1/chat/completions",
523
+ headers=headers,
524
+ json=data,
525
+ timeout=30
526
+ )
527
+
528
+ if response.status_code == 200:
529
+ result = response.json()
530
+ enhanced_content = result["choices"][0]["message"]["content"]
531
+
532
+ return f"""🤖 AI로 강화된 {month} 이벤트 컨셉
533
+
534
+ {enhanced_content}
535
+
536
+ ---
537
+ 💡 이 컨셉들을 기본 컨셉과 결합하여 더욱 창의적인 이벤트를 만들어보세요!
538
+ 📊 각 컨셉의 예상 참여도를 참고하여 최적의 컨셉을 선택하실 수 있습니다."""
539
+ else:
540
+ return "ChatGPT API 요청 실패. API Key와 네트워크 연결을 확인해주세요."
541
+
542
+ except Exception as e:
543
+ return f"ChatGPT API 오류: {str(e)}"
544
+
545
+ # ================== 메인 애플리케이션 ==================
546
+ def create_interface():
547
+ concept_analyzer = ConceptAnalyzer()
548
+ event_manager = EventManager()
549
+ api_integrations = APIIntegrations()
550
+
551
+ with gr.Blocks(title="통합 이벤트 관리 시스템", theme=gr.themes.Soft()) as demo:
552
+
553
+ gr.Markdown("# 🎉 통합 이벤트 관리 시스템")
554
+ gr.Markdown("### 컨셉 분석 + 이벤트 생성 + API 연동을 한 번에!")
555
+
556
+ with gr.Tabs():
557
+ with gr.Tab("🎯 컨셉 분석"):
558
+ with gr.Row():
559
+ with gr.Column():
560
+ gr.Markdown("## 📅 이벤트 기간 설정")
561
+ concept_event_period = gr.Textbox(
562
+ label="이벤트 기간",
563
+ placeholder="예: 2025.8.1 ~ 2025.8.10",
564
+ info="기간을 입력하면 자동으로 월별 컨셉 분석"
565
+ )
566
+
567
+ concept_month = gr.Dropdown(
568
+ choices=[f"{i}월" for i in range(1, 13)],
569
+ label="월 선택",
570
+ value="8월"
571
+ )
572
+
573
+ analyze_concept_btn = gr.Button("🔍 컨셉 분석하기", variant="primary")
574
+
575
+ selected_concept = gr.Dropdown(
576
+ label="분석된 컨셉 선택",
577
+ visible=False
578
+ )
579
+
580
+ custom_concept_input = gr.Textbox(
581
+ label="직접 컨셉 입력",
582
+ placeholder="원하는 컨셉을 직접 입력하세요",
583
+ visible=False,
584
+ info="분석된 컨셉 외에 다른 아이디어가 있다면 입력해주세요"
585
+ )
586
+
587
+ with gr.Column():
588
+ concept_result = gr.Textbox(
589
+ label="컨셉 분석 결과",
590
+ lines=25,
591
+ placeholder="'컨셉 분석하기' 버튼을 클릭하세요"
592
+ )
593
+
594
+ with gr.Tab("📋 이벤트 생성"):
595
+ with gr.Row():
596
+ with gr.Column():
597
+ gr.Markdown("## 📅 기본 정보")
598
+ event_start_date = gr.Textbox(
599
+ label="시작일",
600
+ placeholder="YYYY-MM-DD",
601
+ value="2025-08-01"
602
+ )
603
+
604
+ event_end_date = gr.Textbox(
605
+ label="종료일",
606
+ placeholder="YYYY-MM-DD",
607
+ value="2025-08-10"
608
+ )
609
+
610
+ event_concept_input = gr.Textbox(
611
+ label="이벤트 컨셉",
612
+ placeholder="분석된 컨셉을 선택하거나 직접 입력",
613
+ info="컨셉 분석 탭에서 선택된 컨셉이 자동 입력됩니다"
614
+ )
615
+
616
+ gr.Markdown("## 🎁 상품 설정")
617
+ reward_type_selector = gr.Radio(
618
+ choices=[
619
+ "단일 상품",
620
+ "등급별 상품 (1,2,3등)",
621
+ "선택형 상품",
622
+ "직접 입력"
623
+ ],
624
+ label="상품 구성 방식",
625
+ value="단일 상품"
626
+ )
627
+
628
+ with gr.Group(visible=True) as single_group:
629
+ single_type = gr.Dropdown(
630
+ choices=["네이버페이 금액권", "배달의민족 상품권", "스타벅스 기프트카드", "CGV 영화관람권"],
631
+ label="상품 종류",
632
+ value="네이버페이 금액권"
633
+ )
634
+ single_amount = gr.Number(label="금액 (원)", value=20000, step=1000)
635
+ single_frequency = gr.Textbox(
636
+ label="당첨 주기",
637
+ value="1시간마다 1명씩 하루 24명"
638
+ )
639
+
640
+ with gr.Group(visible=False) as grade_group:
641
+ with gr.Row():
642
+ grade1_amount = gr.Number(label="1등 금액", value=50000)
643
+ grade1_count = gr.Number(label="1등 인원", value=5)
644
+ with gr.Row():
645
+ grade2_amount = gr.Number(label="2등 금액", value=30000)
646
+ grade2_count = gr.Number(label="2등 인원", value=10)
647
+ with gr.Row():
648
+ grade3_amount = gr.Number(label="3등 금액", value=20000)
649
+ grade3_count = gr.Number(label="3등 인원", value=20)
650
+
651
+ with gr.Group(visible=False) as choice_group:
652
+ choice_amount = gr.Number(label="금액 (원)", value=20000)
653
+ choice_frequency = gr.Textbox(
654
+ label="당첨 주기",
655
+ value="1시간마다 1명씩 하루 24명"
656
+ )
657
+
658
+ with gr.Group(visible=False) as custom_group:
659
+ custom_reward = gr.Textbox(
660
+ label="상품 정보 직접 입력",
661
+ lines=5,
662
+ placeholder="상품 정보를 자유롭게 입력하세요"
663
+ )
664
+
665
+ gr.Markdown("## 📞 연락처")
666
+ phone_number = gr.Textbox(label="고객센터", value="1544-1234")
667
+ kakao_id = gr.Textbox(label="카카오톡 ID", value="company_kakao")
668
+
669
+ generate_event_btn = gr.Button("✨ 이벤트 생성하기", variant="primary")
670
+
671
+ with gr.Column():
672
+ with gr.Tabs():
673
+ with gr.Tab("📋 공지사항"):
674
+ event_result = gr.Textbox(
675
+ label="생성된 이벤트 공지사항",
676
+ lines=30,
677
+ interactive=False
678
+ )
679
+
680
+ with gr.Tab("🎨 디자인 가이드"):
681
+ design_result = gr.Textbox(
682
+ label="디자인 가이드",
683
+ lines=20,
684
+ interactive=False
685
+ )
686
+
687
+ with gr.Tab("🔗 API 연동"):
688
+ with gr.Row():
689
+ with gr.Column():
690
+ gr.Markdown("## 🌐 외부 API 설정")
691
+
692
+ with gr.Group():
693
+ gr.Markdown("### 📱 소셜미디어 API")
694
+ enable_instagram = gr.Checkbox(label="Instagram API 연동", value=False)
695
+ instagram_token = gr.Textbox(
696
+ label="Instagram Access Token",
697
+ type="password",
698
+ visible=False
699
+ )
700
+
701
+ with gr.Group():
702
+ gr.Markdown("### 📊 분석 & AI API")
703
+ enable_analytics = gr.Checkbox(label="Google Analytics", value=False)
704
+ ga_tracking_id = gr.Textbox(
705
+ label="GA Tracking ID",
706
+ visible=False
707
+ )
708
+
709
+ enable_chatgpt = gr.Checkbox(label="ChatGPT API (컨셉 생성)", value=False)
710
+ openai_api_key = gr.Textbox(
711
+ label="OpenAI API Key",
712
+ type="password",
713
+ visible=False
714
+ )
715
+
716
+ test_api_btn = gr.Button("🔍 API 연결 테스트", variant="secondary")
717
+ enhance_concept_btn = gr.Button("✨ AI로 컨셉 강화", variant="primary")
718
+
719
+ with gr.Column():
720
+ api_status = gr.Textbox(
721
+ label="API 연동 상태",
722
+ lines=15,
723
+ placeholder="API 설정 후 연결 테스트를 진행하세요"
724
+ )
725
+
726
+ ai_enhanced_result = gr.Textbox(
727
+ label="AI 강화 컨셉",
728
+ lines=15,
729
+ placeholder="ChatGPT API로 컨셉을 더욱 창의적으로 발전시킬 수 있습니다"
730
+ )
731
+
732
+ concepts_state = gr.State([])
733
+
734
+ def handle_period_change(period_text):
735
+ month = concept_analyzer.extract_month_from_period(period_text)
736
+ if month:
737
+ return gr.update(value=month)
738
+ return gr.update()
739
+
740
+ def handle_concept_analysis(month):
741
+ result, concepts = concept_analyzer.analyze_concepts(month)
742
+ return (
743
+ result,
744
+ gr.update(choices=concepts, visible=True, value=concepts[0] if concepts else ""),
745
+ gr.update(visible=True),
746
+ concepts
747
+ )
748
+
749
+ def handle_concept_selection(concept):
750
+ return gr.update(value=concept)
751
+
752
+ def handle_custom_concept_change(custom_concept):
753
+ return gr.update(value=custom_concept)
754
+
755
+ def update_reward_ui(reward_type):
756
+ return (
757
+ gr.update(visible=(reward_type == "단일 상품")),
758
+ gr.update(visible=(reward_type == "등급별 상품 (1,2,3등)")),
759
+ gr.update(visible=(reward_type == "선택형 상품")),
760
+ gr.update(visible=(reward_type == "직접 입력"))
761
+ )
762
+
763
+ def generate_event_template(start_date, end_date, concept, reward_type,
764
+ single_type, single_amount, single_frequency,
765
+ g1_amount, g1_count, g2_amount, g2_count, g3_amount, g3_count,
766
+ choice_amount, choice_frequency, custom_reward,
767
+ phone, kakao):
768
+
769
+ if reward_type == "단일 상품":
770
+ reward_structure = f"{single_type} {int(single_amount):,}원\n{single_frequency}"
771
+ elif reward_type == "등급별 상품 (1,2,3등)":
772
+ reward_structure = f"🥇 1등: {int(g1_amount):,}원 ({int(g1_count)}명)\n🥈 2등: {int(g2_amount):,}원 ({int(g2_count)}명)\n🥉 3등: {int(g3_amount):,}원 ({int(g3_count)}명)"
773
+ elif reward_type == "선택형 상품":
774
+ reward_structure = f"네이버페이 or 배달의민족 {int(choice_amount):,}원\n{choice_frequency}"
775
+ else:
776
+ reward_structure = custom_reward
777
+
778
+ # 컨셉에 따른 트렌디한 카피 생성
779
+ copy_data = concept_analyzer.generate_trendy_copy(concept, "8월")
780
+
781
+ # 기본 이벤트 템플릿 생성
782
+ event_template = event_manager.generate_detailed_comment_event(
783
+ start_date, end_date, concept, reward_structure, kakao, phone
784
+ )
785
+
786
+ # 트렌디한 카피를 템플릿 상단에 추가
787
+ trendy_intro = f"""{copy_data['sub1']}
788
+
789
+ 💫 {copy_data['main']} 💫
790
+
791
+ {copy_data['sub2']}
792
+
793
+ {' '.join(copy_data['hashtags'])}
794
+
795
+ ---
796
+
797
+ """
798
+
799
+ final_template = trendy_intro + event_template
800
+
801
+ # 디자인 가이드 생성
802
+ design_guide = event_manager.generate_design_advice(concept)
803
+
804
+ return final_template, design_guide
805
+
806
+ def toggle_api_inputs(instagram, analytics, chatgpt):
807
+ return (
808
+ gr.update(visible=instagram),
809
+ gr.update(visible=analytics),
810
+ gr.update(visible=chatgpt)
811
+ )
812
+
813
+ def test_api_connections(enable_instagram, instagram_token, enable_analytics, ga_tracking_id, enable_chatgpt, openai_api_key):
814
+ return api_integrations.test_all_connections(enable_instagram, instagram_token, enable_analytics, ga_tracking_id, enable_chatgpt, openai_api_key)
815
+
816
+ def enhance_with_ai(month, openai_key):
817
+ if not openai_key:
818
+ return "OpenAI API Key를 입력해주세요."
819
+ return api_integrations.generate_enhanced_concept_with_chatgpt(month, openai_key)
820
+
821
+ concept_event_period.change(
822
+ handle_period_change,
823
+ inputs=[concept_event_period],
824
+ outputs=[concept_month]
825
+ )
826
+
827
+ analyze_concept_btn.click(
828
+ handle_concept_analysis,
829
+ inputs=[concept_month],
830
+ outputs=[concept_result, selected_concept, custom_concept_input, concepts_state]
831
+ )
832
+
833
+ selected_concept.change(
834
+ handle_concept_selection,
835
+ inputs=[selected_concept],
836
+ outputs=[event_concept_input]
837
+ )
838
+
839
+ custom_concept_input.change(
840
+ handle_custom_concept_change,
841
+ inputs=[custom_concept_input],
842
+ outputs=[event_concept_input]
843
+ )
844
+
845
+ reward_type_selector.change(
846
+ update_reward_ui,
847
+ inputs=[reward_type_selector],
848
+ outputs=[single_group, grade_group, choice_group, custom_group]
849
+ )
850
+
851
+ generate_event_btn.click(
852
+ generate_event_template,
853
+ inputs=[
854
+ event_start_date, event_end_date, event_concept_input, reward_type_selector,
855
+ single_type, single_amount, single_frequency,
856
+ grade1_amount, grade1_count, grade2_amount, grade2_count, grade3_amount, grade3_count,
857
+ choice_amount, choice_frequency, custom_reward,
858
+ phone_number, kakao_id
859
+ ],
860
+ outputs=[event_result, design_result]
861
+ )
862
+
863
+ for checkbox in [enable_instagram, enable_analytics, enable_chatgpt]:
864
+ checkbox.change(
865
+ toggle_api_inputs,
866
+ inputs=[enable_instagram, enable_analytics, enable_chatgpt],
867
+ outputs=[instagram_token, ga_tracking_id, openai_api_key]
868
+ )
869
+
870
+ test_api_btn.click(
871
+ test_api_connections,
872
+ inputs=[enable_instagram, instagram_token, enable_analytics, ga_tracking_id, enable_chatgpt, openai_api_key],
873
+ outputs=[api_status]
874
+ )
875
+
876
+ enhance_concept_btn.click(
877
+ enhance_with_ai,
878
+ inputs=[concept_month, openai_api_key],
879
+ outputs=[ai_enhanced_result]
880
+ )
881
+
882
+ return demo
883
+
884
+ if __name__ == "__main__":
885
+ demo = create_interface()
886
+ demo.launch()