"""iCalendar 파싱 기능"""
import requests
from datetime import datetime
from typing import List, Optional
from icalendar import Calendar
from .models import Reservation, Platform
class ICalParser:
"""iCalendar 파일 파싱"""
@staticmethod
def fetch_ical(url: str) -> str:
"""iCal URL에서 데이터 가져오기"""
response = requests.get(url, timeout=10)
response.raise_for_status()
return response.text
@staticmethod
def parse_ical(ical_data: str, platform: Platform) -> List[Reservation]:
"""iCal 데이터를 Reservation 객체로 변환"""
cal = Calendar.from_ical(ical_data)
reservations = []
for component in cal.walk():
if component.name == "VEVENT":
# 이벤트 정보 추출
summary = str(component.get('summary', 'Unknown'))
start = component.get('dtstart').dt
end = component.get('dtend').dt
uid = str(component.get('uid', ''))
description = str(component.get('description', ''))
# datetime 변환 (date인 경우 처리)
if isinstance(start, datetime):
start_time = start
else:
start_time = datetime.combine(start, datetime.min.time())
if isinstance(end, datetime):
end_time = end
else:
end_time = datetime.combine(end, datetime.min.time())
# 고객 이름 추출 (summary에서 파싱)
customer_name = ICalParser._extract_customer_name(summary, description)
# 가격 추출 (description에서 파싱)
price = ICalParser._extract_price(description)
reservation = Reservation(
id=f"{platform}_{uid}",
platform=platform,
customer_name=customer_name,
start_time=start_time,
end_time=end_time,
price=price,
status="confirmed",
notes=description
)
reservations.append(reservation)
return reservations
@staticmethod
def _extract_customer_name(summary: str, description: str) -> str:
"""summary나 description에서 고객 이름 추출"""
# 플랫폼별로 다른 형식일 수 있음
# 예: "홍길동 - 예약", "Reservation by 김철수" 등
# 간단한 파싱 로직
if ' - ' in summary:
return summary.split(' - ')[0].strip()
elif 'Reserved by' in summary:
return summary.split('Reserved by')[-1].strip()
else:
return summary.strip()
@staticmethod
def _extract_price(description: str) -> float:
"""description에서 가격 추출"""
# 간단한 가격 파싱 (숫자만 추출)
# 실제로는 플랫폼별로 다른 형식 처리 필요
import re
price_match = re.search(r'[\₩$]\s*([0-9,]+)', description)
if price_match:
price_str = price_match.group(1).replace(',', '')
return float(price_str)
return 0.0
@classmethod
def sync_platform(cls, platform: Platform, ical_url: str) -> List[Reservation]:
"""플랫폼의 iCal URL에서 예약 동기화"""
try:
ical_data = cls.fetch_ical(ical_url)
reservations = cls.parse_ical(ical_data, platform)
return reservations
except Exception as e:
print(f"Error syncing {platform}: {e}")
return []