event01 / app.py
aliceblue11's picture
Update app.py
c21e695 verified
raw
history blame
40.5 kB
"""
이벤트 공지사항 생성기 - 완전 버전
그라디오 최신 버전 지원
"""
import gradio as gr
from datetime import datetime, timedelta
from typing import List, Dict, Any
import json
import tempfile
import os
class EventGenerator:
"""이벤트 생성기 메인 클래스"""
def __init__(self):
self.monthly_data = {
1: {
"holidays": ["신정", "설날", "대보름"],
"special_days": ["새해", "신년", "다이어트의 달"],
"seasons": ["겨울", "새해맞이", "신년다짐"],
"trends": ["새해 계획", "다이어트", "정리정돈", "미니멀라이프"],
"colors": ["#FF6B6B", "#4ECDC4", "#45B7D1", "#96CEB4", "#FFEAA7"]
},
2: {
"holidays": ["밸런타인데이", "정월대보름"],
"special_days": ["초콜릿데이", "로즈데이"],
"seasons": ["겨울", "입춘", "매화꽃"],
"trends": ["러브", "로맨스", "셀프케어", "따뜻함"],
"colors": ["#FF69B4", "#FFB6C1", "#DC143C", "#FFC0CB", "#8B0000"]
},
3: {
"holidays": ["삼일절", "화이트데이"],
"special_days": ["여성의 날", "화이트데이"],
"seasons": ["봄", "벚꽃", "춘분", "개화"],
"trends": ["봄맞이", "새학기", "벚꽃놀이", "봄나들이"],
"colors": ["#FFB6C1", "#98FB98", "#87CEEB", "#F0E68C", "#DDA0DD"]
},
4: {
"holidays": ["만우절", "식목일"],
"special_days": ["블랙데이", "킹데이"],
"seasons": ["봄", "벚꽃만개", "꽃구경"],
"trends": ["벚꽃축제", "봄피크닉", "새학기적응", "아웃도어"],
"colors": ["#FFB6C1", "#98FB98", "#F0E68C", "#DDA0DD", "#87CEEB"]
},
5: {
"holidays": ["어린이날", "어버이날", "스승의날", "부처님오신날"],
"special_days": ["가정의 달", "로즈데이", "감사데이"],
"seasons": ["봄", "신록", "야외활동"],
"trends": ["가족사랑", "감사", "나들이", "어린이날선물"],
"colors": ["#32CD32", "#FFB6C1", "#87CEEB", "#F0E68C", "#DDA0DD"]
},
6: {
"holidays": ["현충일", "단오"],
"special_days": ["키스데이", "패밀리데이"],
"seasons": ["초여름", "장마준비", "여름나기"],
"trends": ["여름준비", "다이어트", "워터파크", "바캉스준비"],
"colors": ["#00CED1", "#FFD700", "#FF6347", "#32CD32", "#FF69B4"]
},
7: {
"holidays": ["제헌절", "초복", "중복"],
"special_days": ["실버데이", "썸머데이"],
"seasons": ["여름", "장마", "휴가철"],
"trends": ["여름휴가", "워터액티비티", "시원한음식", "휴가패션"],
"colors": ["#00BFFF", "#FFD700", "#FF6347", "#32CD32", "#FF69B4"]
},
8: {
"holidays": ["광복절", "말복"],
"special_days": ["그린데이", "썸머바캉스"],
"seasons": ["여름", "휴가철", "더위절정"],
"trends": ["여름휴가절정", "바다여행", "축제", "여름추억"],
"colors": ["#00BFFF", "#FF6347", "#FFD700", "#32CD32", "#FF69B4"]
},
9: {
"holidays": ["추석", "추분"],
"special_days": ["포토데이", "뮤직데이"],
"seasons": ["가을", "추석연휴", "선선함"],
"trends": ["추석준비", "가을패션", "독서의계절", "문화생활"],
"colors": ["#FF8C00", "#DC143C", "#B8860B", "#CD853F", "#D2691E"]
},
10: {
"holidays": ["개천절", "한글날"],
"special_days": ["와인데이", "커피데이"],
"seasons": ["가을", "단풍", "쌀쌀함"],
"trends": ["가을단풍", "독서", "카페문화", "가을나들이"],
"colors": ["#FF8C00", "#DC143C", "#B8860B", "#8B4513", "#A0522D"]
},
11: {
"holidays": ["빼빼로데이", "수능"],
"special_days": ["무비데이", "오렌지데이"],
"seasons": ["늦가을", "쌀쌀함", "겨울준비"],
"trends": ["빼빼로데이", "수능응원", "겨울준비", "연말준비"],
"colors": ["#8B4513", "#A0522D", "#CD853F", "#D2691E", "#FF8C00"]
},
12: {
"holidays": ["크리스마스", "성탄절", "동지"],
"special_days": ["허그데이", "키스데이"],
"seasons": ["겨울", "연말", "크리스마스"],
"trends": ["크리스마스", "연말파티", "선물", "한해마무리"],
"colors": ["#DC143C", "#228B22", "#FFD700", "#800080", "#FF69B4"]
}
}
self.event_templates = {
"댓글 달기 이벤트": {
"steps": ["해당 게시글 찾아가기", "감성적인 댓글 작성하기", "댓글 등록 완료"],
"description": "지정된 게시글에 댓글을 달아주세요"
},
"게시글 작성 이벤트": {
"steps": ["이벤트 주제 확인하기", "창의적인 게시글 작성하기", "해시태그 포함하여 업로드"],
"description": "주제에 맞는 게시글을 작성해주세요"
},
"좋아요/공감 이벤트": {
"steps": ["이벤트 게시글 확인하기", "좋아요 버튼 클릭하기", "추가 액션 완료하기"],
"description": "마음에 드는 게시글에 좋아요를 눌러주세요"
},
"출석체크 이벤트": {
"steps": ["매일 커뮤니티 접속하기", "출석체크 버튼 클릭하기", "연속 출석 달성하기"],
"description": "매일 커뮤니티에 방문하여 출석체크를 해주세요"
},
"추천인 이벤트": {
"steps": ["초대 링크 생성하기", "친구에게 링크 공유하기", "친구 가입 완료 확인하기"],
"description": "친구를 초대하고 함께 이벤트에 참여해주세요"
},
"사진 업로드 이벤트": {
"steps": ["테마에 맞는 사진 촬영하기", "사진 업로드하기", "설명글과 함께 공유하기"],
"description": "테마에 맞는 사진을 업로드해주세요"
},
"퀴즈/설문 이벤트": {
"steps": ["퀴즈 문제 확인하기", "정답 또는 의견 제출하기", "제출 완료 확인하기"],
"description": "퀴즈를 풀거나 설문에 참여해주세요"
}
}
def analyze_monthly_concepts(self, month: int, year: int = 2025) -> List[Dict[str, Any]]:
"""월별 컨셉 분석"""
month_data = self.monthly_data.get(month, {})
concepts = []
# 컨셉 1: 주요 기념일 기반
if month_data.get("holidays"):
main_holiday = month_data["holidays"][0]
concepts.append({
"name": f"{main_holiday} 특별 이벤트",
"theme": f"{main_holiday}를 테마로 한 감성 이벤트",
"catchphrase": f"💕 {main_holiday}과 함께 특별한 추억을 만들어요!",
"reason": f"{month}월의 대표 기념일인 {main_holiday}로 높은 관심과 참여도 예상",
"colors": month_data.get("colors", ["#FF69B4"])[:3],
"participation_score": 8.5,
"participation_reason": "주요 기념일로 인한 높은 관심도와 시즌성",
"event_style": "댓글 이벤트 + 인증샷 업로드",
"competitive_edge": "시즌 특화 컨텐츠로 차별화",
"target_appeal": "기념일 감성과 공감대 형성"
})
# 컨셉 2: 계절/트렌드 기반
if month_data.get("trends"):
trend_theme = month_data["trends"][0]
concepts.append({
"name": f"{trend_theme} 챌린지",
"theme": f"최신 {trend_theme} 트렌드 참여형 이벤트",
"catchphrase": f"✨ 지금 핫한 {trend_theme}! 함께 도전해요!",
"reason": f"현재 인기 트렌드인 {trend_theme}로 젊은 층 어필",
"colors": month_data.get("colors", ["#4ECDC4"])[1:4],
"participation_score": 8.0,
"participation_reason": "최신 트렌드로 인한 화제성과 참여욕구",
"event_style": "챌린지 참여 + SNS 공유",
"competitive_edge": "트렌드 선도적 이벤트",
"target_appeal": "트렌드 민감층과 SNS 활용"
})
# 컨셉 3: 계절감 기반
if month_data.get("seasons"):
season_theme = month_data["seasons"][0]
concepts.append({
"name": f"{season_theme} 라이프 이벤트",
"theme": f"{season_theme} 계절 맞이 라이프스타일 이벤트",
"catchphrase": f"🌸 {season_theme}과 함께하는 일상의 소소한 행복!",
"reason": f"{season_theme} 계절감으로 자연스러운 참여 유도",
"colors": month_data.get("colors", ["#98FB98"])[2:5],
"participation_score": 7.5,
"participation_reason": "계절적 공감대와 일상 연관성",
"event_style": "포토 챌린지 + 후기 공유",
"competitive_edge": "계절별 맞춤 컨텐츠",
"target_appeal": "일상 속 계절감과 감성"
})
# 컨셉 4: 커뮤니티 소통 기반
concepts.append({
"name": f"{month}월 우리들의 이야기",
"theme": "커뮤니티 멤버 간 소통과 공감 이벤트",
"catchphrase": f"💬 {month}월, 우리의 특별한 이야기를 들려주세요!",
"reason": "커뮤니티 결속력 강화와 지속적 참여 유도",
"colors": month_data.get("colors", ["#87CEEB"])[-3:],
"participation_score": 7.0,
"participation_reason": "커뮤니티 애착도와 소속감 기반 참여",
"event_style": "스토리텔링 + 공감 이벤트",
"competitive_edge": "진정성 있는 커뮤니티 소통",
"target_appeal": "소속감과 공감대 형성"
})
# 컨셉 5: 스페셜 데이 기반
if month_data.get("special_days"):
special_day = month_data["special_days"][0]
concepts.append({
"name": f"{special_day} 스페셜 위크",
"theme": f"{special_day} 맞이 특별 혜택 이벤트",
"catchphrase": f"🎁 {special_day} 특별한 선물이 기다려요!",
"reason": f"{special_day}의 특별함을 활용한 프리미엄 이벤트",
"colors": month_data.get("colors", ["#FFB6C1"])[:3],
"participation_score": 7.8,
"participation_reason": "특별한 날에 대한 기대감과 혜택 관심",
"event_style": "미션 완료 + 럭키박스",
"competitive_edge": "특별 혜택과 깜짝 이벤트",
"target_appeal": "특별함과 혜택에 대한 기대"
})
return concepts
def generate_event_notice(self, concept_data: Dict, event_type: str, custom_event: str = None) -> str:
"""완성된 이벤트 공지사항 생성"""
concept_name = concept_data.get("name", "특별 이벤트")
catchphrase = concept_data.get("catchphrase", "✨ 특별한 이벤트에 참여하세요!")
theme = concept_data.get("theme", "커뮤니티 이벤트")
# 이벤트 기간 설정
now = datetime.now()
start_date = now.strftime("%Y.%m.%d")
end_date = (now + timedelta(days=7)).strftime("%Y.%m.%d")
# 템플릿 선택
if custom_event and event_type == "직접 입력":
template = {
"description": custom_event,
"steps": ["이벤트 내용 확인하기", "요구사항에 맞게 참여하기", "참여 완료 확인하기"]
}
else:
template = self.event_templates.get(event_type, self.event_templates["댓글 달기 이벤트"])
# 공지사항 생성
notice = f"""{catchphrase}
🎉 {concept_name} 🎉
📅 이벤트 기간: {start_date} ~ {end_date} 23:59
========================
✨ EVENT
{theme}을 테마로 한 특별한 이벤트에 참여하세요!
많은 분들의 적극적인 참여를 기다리고 있어요 💕
📅 이벤트 기간: {start_date} ~ {end_date}
========================
🎯 STEP 1
{template["steps"][0]}
* 이벤트 게시글을 꼼꼼히 확인해주세요!
🎯 STEP 2
{template["steps"][1]}
* 진심이 담긴 따뜻한 마음으로 참여해주세요
🎯 STEP 3
{template["steps"][2]}
* 모든 과정을 완료하시면 참여 완료입니다!
=================
🎁 당첨혜택
✨ 1등 (1명): 스타벅스 5만원 기프트카드
🎉 2등 (3명): 베스킨라빈스 아이스크림 쿠폰
💝 3등 (10명): 편의점 5천원 상품권
🌟 참가상 (50명): 모바일 치킨 쿠폰
📋 추첨 방식: 참여자 중 무작위 추첨
========================
👥 이벤트 대상
✅ 커뮤니티 정회원 (가입 후 7일 경과)
✅ 만 18세 이상 성인
✅ 이벤트 기간 내 정상 참여자
(*중복 참여, 어뷰징 계정 제외)
========================
📮 수령방법
1️⃣ 당첨자 발표: 이벤트 종료 후 3일 이내
2️⃣ 개별 메시지를 통한 당첨 안내
3️⃣ 본인 확인 후 7일 이내 회신 필수
4️⃣ 모바일 쿠폰/기프트카드 발송
📞 문의처: 커뮤니티 고객센터
🕐 수령 기한: 당첨 안내 후 30일 이내
=========================
⚠️ 꼭 확인하세요!
※ 부적절한 내용의 댓글/게시글은 삭제될 수 있습니다
※ 중복 계정이나 어뷰징으로 의심되는 참여는 제외됩니다
※ 당첨자는 본인 확인을 위해 추가 정보 요청이 있을 수 있습니다
※ 상품은 현금으로 교환되지 않으며, 재판매가 불가합니다
※ 이벤트 내용은 운영진의 판단에 따라 변경될 수 있습니다
※ 문의사항은 고객센터를 통해 연락해주세요
===========================
📞 고객센터: 1234-5678
🕐 운영시간: 평일 09:30~18:00 (점심시간 12:00~13:00)
💬 카카오톡: @event_community
※ 주말 및 공휴일 휴무
💝 많은 분들의 참여 부탁드려요! 감사합니다 💕"""
return notice.strip()
def count_text_stats(self, text: str) -> str:
"""텍스트 통계 계산"""
total_chars = len(text)
chars_no_space = len(text.replace(" ", "").replace("\n", ""))
words = len(text.split())
lines = len(text.split("\n"))
return f"총 글자수: {total_chars:,}자 | 공백제외: {chars_no_space:,}자 | 단어수: {words:,}개 | 줄수: {lines:,}줄"
def create_app():
"""그라디오 앱 생성"""
generator = EventGenerator()
# 커스텀 CSS
custom_css = """
.main-header {
text-align: center;
padding: 30px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border-radius: 15px;
margin-bottom: 25px;
box-shadow: 0 4px 15px rgba(0,0,0,0.1);
}
.input-section {
background: #f8f9fa;
padding: 25px;
border-radius: 15px;
box-shadow: 0 2px 10px rgba(0,0,0,0.05);
margin-bottom: 20px;
}
.output-section {
background: white;
padding: 25px;
border-radius: 15px;
box-shadow: 0 2px 10px rgba(0,0,0,0.05);
}
.concept-card {
background: linear-gradient(45deg, #e3f2fd, #f1f8e9);
padding: 20px;
border-radius: 12px;
margin: 15px 0;
border-left: 5px solid #2196f3;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.stats-box {
background: #fff3cd;
padding: 10px;
border-radius: 8px;
border: 1px solid #ffeaa7;
margin-top: 10px;
}
"""
with gr.Blocks(
title="🎉 AI 이벤트 공지사항 생성기",
theme=gr.themes.Soft(),
css=custom_css
) as demo:
# 헤더
with gr.Column(elem_classes="main-header"):
gr.Markdown("""
# 🎉 AI 이벤트 공지사항 생성기
### 실시간 트렌드 분석으로 완벽한 이벤트 기획을 도와드립니다
#### 20-40대 여성 타겟 커뮤니티 이벤트 전문 생성기
""")
with gr.Row():
# 좌측: 입력 영역
with gr.Column(scale=1, elem_classes="input-section"):
gr.Markdown("## ⚙️ 기본 설정")
with gr.Row():
year_input = gr.Number(
value=2025,
label="📅 연도",
minimum=2024,
maximum=2030,
step=1
)
month_input = gr.Dropdown(
choices=[f"{i}월" for i in range(1, 13)],
label="📅 이벤트 월 선택",
value=f"{datetime.now().month}월"
)
analyze_btn = gr.Button(
"🧠 AI 컨셉 분석 시작",
variant="secondary",
size="lg"
)
# 컨셉 선택 영역
with gr.Group(visible=False) as concept_group:
gr.Markdown("### 🎨 추천 컨셉 선택")
concept_selector = gr.Dropdown(
label="컨셉을 선택해주세요",
interactive=True
)
concept_preview = gr.Textbox(
label="📊 선택된 컨셉 미리보기",
lines=8,
interactive=False
)
gr.Markdown("## 🎯 이벤트 설정")
event_type_selector = gr.Dropdown(
choices=[
"댓글 달기 이벤트",
"게시글 작성 이벤트",
"좋아요/공감 이벤트",
"출석체크 이벤트",
"추천인 이벤트",
"사진 업로드 이벤트",
"퀴즈/설문 이벤트",
"직접 입력"
],
label="🎯 이벤트 유형 선택",
value="댓글 달기 이벤트"
)
custom_event_input = gr.Textbox(
label="✏️ 커스텀 이벤트 설명",
placeholder="'직접 입력' 선택시 원하는 이벤트 내용을 자세히 설명해주세요",
visible=False,
lines=4
)
generate_btn = gr.Button(
"✨ 완성된 공지사항 생성하기",
variant="primary",
size="lg",
visible=False
)
# 우측: 결과 출력 영역
with gr.Column(scale=2, elem_classes="output-section"):
with gr.Tabs() as tabs:
with gr.TabItem("🧠 AI 컨셉 분석"):
concept_analysis_output = gr.Markdown(
value="👆 먼저 좌측에서 연도와 월을 선택한 후 'AI 컨셉 분석 시작' 버튼을 클릭해주세요",
elem_classes="concept-card"
)
with gr.TabItem("📝 완성된 공지사항"):
final_notice_output = gr.Textbox(
label="생성된 이벤트 공지사항",
lines=35,
placeholder="컨셉 선택 후 '완성된 공지사항 생성하기' 버튼을 클릭하면 결과가 나타납니다",
show_copy_button=True,
max_lines=50
)
# 통계 및 버튼
with gr.Row():
text_stats_output = gr.Textbox(
label="📊 텍스트 통계",
lines=1,
interactive=False,
visible=False,
elem_classes="stats-box"
)
with gr.Row():
download_btn = gr.DownloadButton(
"💾 텍스트 파일로 다운로드",
size="sm",
variant="secondary",
visible=False
)
regenerate_btn = gr.Button(
"🔄 다시 생성하기",
size="sm",
visible=False
)
with gr.TabItem("🎨 컨셉 상세정보"):
concept_details_output = gr.JSON(
label="선택된 컨셉의 상세 정보",
visible=False
)
# 상태 관리
concepts_state = gr.State([])
selected_concept_state = gr.State(None)
# 이벤트 핸들러 함수들
def handle_concept_analysis(year, month):
"""AI 컨셉 분석 처리"""
try:
month_num = int(month.replace('월', ''))
concepts = generator.analyze_monthly_concepts(month_num, year)
concept_choices = [f"{concept['name']} - {concept['theme']}" for concept in concepts]
# 분석 결과 마크다운 생성
analysis_md = f"# 🎯 {year}{month} AI 분석 결과\n\n"
analysis_md += f"**분석 완료:** {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n"
analysis_md += f"**총 {len(concepts)}개 컨셉 추천**\n\n"
for i, concept in enumerate(concepts, 1):
colors_display = " ".join([f"`{color}`" for color in concept['colors'][:3]])
analysis_md += f"""
## {i}. {concept['name']}
**🏷️ 테마:** {concept['theme']}
**🎯 타겟 어필:** {concept['target_appeal']}
**⭐ 예상 참여도:** {concept['participation_score']}/10점
**🎪 추천 이벤트:** {concept['event_style']}
**🎨 색상 팔레트:** {colors_display}
**💡 선정 이유:** {concept['reason']}
---
"""
return (
gr.update(visible=True), # concept_group
gr.update(choices=concept_choices, value=concept_choices[0] if concept_choices else None), # concept_selector
gr.update(visible=True), # generate_btn
analysis_md, # concept_analysis_output
concepts # concepts_state
)
except Exception as e:
error_message = f"❌ 컨셉 분석 중 오류가 발생했습니다: {str(e)}"
return (
gr.update(visible=False),
gr.update(choices=[], value=None),
gr.update(visible=False),
error_message,
[]
)
def handle_concept_selection(selected_concept_name, concepts_data):
"""컨셉 선택 처리"""
try:
if selected_concept_name and concepts_data:
selected_idx = next(i for i, c in enumerate(concepts_data)
if f"{c['name']} - {c['theme']}" == selected_concept_name)
selected_concept = concepts_data[selected_idx]
# 미리보기 텍스트 생성
preview_text = f"""🎨 컨셉명: {selected_concept['name']}
🏷️ 테마: {selected_concept['theme']}
💬 캐치프레이즈: {selected_concept['catchphrase']}
🎯 타겟 어필: {selected_concept['target_appeal']}
⭐ 예상 참여도: {selected_concept['participation_score']}/10점
📊 참여 근거: {selected_concept['participation_reason']}
🎪 추천 이벤트: {selected_concept['event_style']}
🎨 색상 팔레트: {', '.join(selected_concept['colors'][:3])}
💡 차별화 포인트: {selected_concept['competitive_edge']}"""
return preview_text, selected_concept, gr.update(value=selected_concept, visible=True)
return "", None, gr.update(visible=False)
except Exception as e:
return f"❌ 컨셉 선택 오류: {str(e)}", None, gr.update(visible=False)
def handle_event_type_change(event_type):
"""이벤트 유형 변경 처리"""
return gr.update(visible=(event_type == "직접 입력"))
def handle_final_generation(year, month, selected_concept, event_type, custom_event):
"""최종 공지사항 생성 처리"""
try:
if not selected_concept:
return (
"❌ 먼저 컨셉을 선택해주세요!",
gr.update(visible=False),
gr.update(visible=False),
gr.update(visible=False),
""
)
# 공지사항 생성
notice = generator.generate_event_notice(
concept_data=selected_concept,
event_type=event_type,
custom_event=custom_event
)
# 텍스트 통계
stats = generator.count_text_stats(notice)
# 다운로드 파일 준비
def prepare_download():
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"event_notice_{timestamp}.txt"
temp_file = tempfile.NamedTemporaryFile(
mode='w',
suffix='.txt',
delete=False,
encoding='utf-8'
)
temp_file.write(notice)
temp_file.close()
return temp_file.name
return (
notice, # final_notice_output
gr.update(visible=True, value=stats), # text_stats_output
gr.update(visible=True), # download_btn
gr.update(visible=True), # regenerate_btn
prepare_download() # 다운로드 파일
)
except Exception as e:
error_message = f"❌ 공지사항 생성 중 오류가 발생했습니다: {str(e)}"
return (
error_message,
gr.update(visible=False),
gr.update(visible=False),
gr.update(visible=False),
""
)
def handle_regeneration(year, month, selected_concept, event_type, custom_event):
"""공지사항 재생성"""
return handle_final_generation(year, month, selected_concept, event_type, custom_event)
# 이벤트 바인딩
analyze_btn.click(
handle_concept_analysis,
inputs=[year_input, month_input],
outputs=[concept_group, concept_selector, generate_btn, concept_analysis_output, concepts_state]
)
concept_selector.change(
handle_concept_selection,
inputs=[concept_selector, concepts_state],
outputs=[concept_preview, selected_concept_state, concept_details_output]
)
event_type_selector.change(
handle_event_type_change,
inputs=[event_type_selector],
outputs=[custom_event_input]
)
generate_btn.click(
handle_final_generation,
inputs=[year_input, month_input, selected_concept_state, event_type_selector, custom_event_input],
outputs=[final_notice_output, text_stats_output, download_btn, regenerate_btn, download_btn]
)
regenerate_btn.click(
handle_regeneration,
inputs=[year_input, month_input, selected_concept_state, event_type_selector, custom_event_input],
outputs=[final_notice_output, text_stats_output, download_btn, regenerate_btn, download_btn]
)
return demo
def main():
"""메인 실행 함수"""
print("🎉 이벤트 공지사항 생성기를 시작합니다...")
print("📚 그라디오 최신 버전으로 실행 중...")
try:
# 애플리케이션 생성
demo = create_app()
# 서버 실행
print("🚀 서버를 시작합니다...")
demo.launch(
server_name="0.0.0.0",
server_port=7860,
share=True,
show_tips=True,
show_error=True
)
except Exception as e:
print(f"❌ 애플리케이션 시작 중 오류 발생: {e}")
import traceback
traceback.print_exc()
if __name__ == "__main__":
main()"""
이벤트 공지사항 생성기 - 기본 버전 (MVP)
"""
import gradio as gr
from datetime import datetime
from typing import List, Dict, Any
class BasicEventGenerator:
"""기본 이벤트 생성기"""
def __init__(self):
self.monthly_data = {
1: {"holidays": ["신정", "설날"], "trends": ["새해 계획", "다이어트"], "colors": ["#FF6B6B", "#4ECDC4", "#45B7D1"]},
2: {"holidays": ["밸런타인데이"], "trends": ["러브", "로맨스"], "colors": ["#FF69B4", "#FFB6C1", "#DC143C"]},
3: {"holidays": ["삼일절", "화이트데이"], "trends": ["봄맞이", "벚꽃놀이"], "colors": ["#FFB6C1", "#98FB98", "#87CEEB"]},
4: {"holidays": ["만우절"], "trends": ["벚꽃축제", "봄피크닉"], "colors": ["#98FB98", "#F0E68C", "#DDA0DD"]},
5: {"holidays": ["어린이날", "어버이날"], "trends": ["가족사랑", "나들이"], "colors": ["#32CD32", "#FFB6C1", "#87CEEB"]},
6: {"holidays": ["현충일"], "trends": ["여름준비", "바캉스준비"], "colors": ["#00CED1", "#FFD700", "#FF6347"]},
7: {"holidays": ["제헌절"], "trends": ["여름휴가", "바다여행"], "colors": ["#00BFFF", "#FFD700", "#FF6347"]},
8: {"holidays": ["광복절"], "trends": ["여름휴가절정", "축제"], "colors": ["#00BFFF", "#FF6347", "#FFD700"]},
9: {"holidays": ["추석"], "trends": ["추석준비", "가을패션"], "colors": ["#FF8C00", "#DC143C", "#B8860B"]},
10: {"holidays": ["개천절", "한글날"], "trends": ["가을단풍", "독서"], "colors": ["#FF8C00", "#DC143C", "#B8860B"]},
11: {"holidays": ["빼빼로데이"], "trends": ["빼빼로데이", "겨울준비"], "colors": ["#8B4513", "#A0522D", "#CD853F"]},
12: {"holidays": ["크리스마스"], "trends": ["크리스마스", "연말파티"], "colors": ["#DC143C", "#228B22", "#FFD700"]}
}
def analyze_month_concepts(self, month: int) -> List[Dict[str, Any]]:
"""월별 간단한 컨셉 분석"""
month_data = self.monthly_data.get(month, {})
concepts = []
# 컨셉 1: 기념일 기반
if month_data.get("holidays"):
holiday = month_data["holidays"][0]
concepts.append({
"name": f"{holiday} 특별 이벤트",
"theme": f"{holiday}를 테마로 한 이벤트",
"score": 8.5,
"colors": month_data.get("colors", ["#FF69B4"])
})
# 컨셉 2: 트렌드 기반
if month_data.get("trends"):
trend = month_data["trends"][0]
concepts.append({
"name": f"{trend} 챌린지",
"theme": f"{trend} 트렌드 이벤트",
"score": 7.8,
"colors": month_data.get("colors", ["#87CEEB"])
})
# 컨셉 3: 커뮤니티 기반
concepts.append({
"name": f"{month}월 소통 이벤트",
"theme": "커뮤니티 멤버 소통 이벤트",
"score": 7.0,
"colors": month_data.get("colors", ["#98FB98"])
})
return concepts
def generate_notice(self, concept: Dict, event_type: str) -> str:
"""기본 공지사항 생성"""
now = datetime.now()
start_date = f"{now.year}.{now.month}.{now.day}"
end_date = f"{now.year}.{now.month}.{now.day + 7}"
notice = f"""
💕 {concept['name']}에 참여하세요!
🎉 {concept['name']} 🎉
📅 이벤트 기간: {start_date} ~ {end_date} 23:59
========================
✨ EVENT
{concept['theme']}을 테마로 한 특별한 이벤트입니다!
많은 분들의 적극적인 참여를 기다리고 있어요 💕
========================
🎯 참여 방법
1️⃣ 이벤트 게시글 확인하기
2️⃣ {event_type} 참여하기
3️⃣ 참여 완료!
=================
🎁 당첨혜택
✨ 1등 (1명): 스타벅스 5만원 기프트카드
🎉 2등 (3명): 베스킨라빈스 쿠폰
💝 3등 (10명): 편의점 5천원 상품권
📋 추첨: 참여자 중 무작위 추첨
========================
👥 이벤트 대상
✅ 커뮤니티 정회원
✅ 만 18세 이상
✅ 이벤트 기간 내 참여자
========================
⚠️ 주의사항
※ 부적절한 참여는 제외됩니다
※ 중복 계정 참여 불가
※ 당첨자는 본인 확인 필요
===========================
📞 문의: 1234-5678
💬 카카오톡: @event_community
💝 많은 참여 부탁드려요! 감사합니다 💕
"""
return notice.strip()
def create_interface():
"""그라디오 인터페이스 생성"""
generator = BasicEventGenerator()
with gr.Blocks(title="이벤트 공지사항 생성기") as demo:
gr.Markdown("""
# 🎉 이벤트 공지사항 생성기
### 간편하게 이벤트 공지사항을 만들어보세요!
""")
with gr.Row():
with gr.Column():
gr.Markdown("## ⚙️ 설정")
month_input = gr.Dropdown(
choices=[f"{i}월" for i in range(1, 13)],
label="📅 이벤트 월",
value=f"{datetime.now().month}월"
)
event_type_input = gr.Dropdown(
choices=["댓글 달기", "게시글 작성", "좋아요 누르기", "출석체크"],
label="🎯 이벤트 유형",
value="댓글 달기"
)
analyze_btn = gr.Button("🧠 컨셉 분석하기", variant="secondary")
concept_dropdown = gr.Dropdown(
label="🎨 컨셉 선택",
visible=False
)
generate_btn = gr.Button("✨ 공지사항 생성하기", variant="primary", visible=False)
with gr.Column():
gr.Markdown("## 📝 결과")
concept_result = gr.Textbox(
label="컨셉 분석 결과",
lines=8,
placeholder="먼저 '컨셉 분석하기' 버튼을 클릭하세요"
)
final_result = gr.Textbox(
label="생성된 공지사항",
lines=20,
placeholder="컨셉을 선택하고 '공지사항 생성하기' 버튼을 클릭하세요",
show_copy_button=True
)
# 상태 변수
concepts_state = gr.State([])
selected_concept_state = gr.State(None)
def handle_analyze(month):
"""컨셉 분석 처리"""
try:
month_num = int(month.replace('월', ''))
concepts = generator.analyze_month_concepts(month_num)
# 결과 텍스트 생성
result_text = f"# {month} 추천 컨셉\n\n"
concept_choices = []
for i, concept in enumerate(concepts, 1):
result_text += f"## {i}. {concept['name']}\n"
result_text += f"- 테마: {concept['theme']}\n"
result_text += f"- 예상 점수: {concept['score']}/10점\n\n"
concept_choices.append(concept['name'])
return (
result_text,
gr.update(visible=True, choices=concept_choices, value=concept_choices[0]),
gr.update(visible=True),
concepts
)
except Exception as e:
return f"❌ 오류: {str(e)}", gr.update(visible=False), gr.update(visible=False), []
def handle_concept_select(concept_name, concepts):
"""컨셉 선택 처리"""
if concept_name and concepts:
selected = next((c for c in concepts if c['name'] == concept_name), None)
return selected
return None
def handle_generate(concept, event_type):
"""공지사항 생성 처리"""
if concept:
notice = generator.generate_notice(concept, event_type)
return notice
return "❌ 컨셉을 먼저 선택해주세요!"
# 이벤트 연결
analyze_btn.click(
handle_analyze,
inputs=[month_input],
outputs=[concept_result, concept_dropdown, generate_btn, concepts_state]
)
concept_dropdown.change(
handle_concept_select,
inputs=[concept_dropdown, concepts_state],
outputs=[selected_concept_state]
)
generate_btn.click(
handle_generate,
inputs=[selected_concept_state, event_type_input],
outputs=[final_result]
)
return demo
if __name__ == "__main__":
demo = create_interface()
demo.launch(
server_name="0.0.0.0",
server_port=7860,
share=True
)