Skip to main content

설치

pip install sajuapi

빠른 시작

from sajuapi import SajuClient, SajuCalculator

# 클라이언트 초기화
client = SajuClient(api_key="bs_live_xxx")

# 사주 계산 (로컬 실행)
saju = SajuCalculator.calculate(
    year=1990,
    month=5,
    day=15,
    hour=14,
    gender="male"
)

# 일일 운세 조회
fortune = client.get_daily_fortune(
    saju=saju,
    user_name="홍길동",
    model="haiku"
)

print(fortune.today_fortune.score)  # 78

설정

client = SajuClient(
    api_key="bs_live_xxx",
    base_url="https://api.sajuapi.dev",  # 선택
    timeout=30,                                 # 초
    max_retries=3
)

# 또는 환경 변수 사용
import os
os.environ["SAJU_API_KEY"] = "bs_live_xxx"

client = SajuClient()  # 환경 변수에서 읽음

SajuCalculator

로컬에서 사주팔자 계산:
from sajuapi import SajuCalculator

saju = SajuCalculator.calculate(
    year=1990,
    month=5,
    day=15,
    hour=14,           # 24시간 형식, 모르면 None
    minute=30,         # 선택
    gender="male",
    calendar_type="solar"  # "solar" 또는 "lunar"
)

# 사주 접근
print(saju.pillars.day.stem.hangul)  # "병"
print(saju.day_master.element)        # "fire"
print(saju.element_balance.weakest)   # "water"

API 메서드

get_daily_fortune

fortune = client.get_daily_fortune(
    saju=saju,
    user_name="홍길동",
    model="haiku",           # "haiku", "sonnet", "gpt4o"
    date="2024-01-15",       # 선택
    fortune_type="all"       # "all", "fortune_only", "character"
)

# 응답 접근
print(fortune.character.day_master)           # "병화"
print(fortune.character.emoji)                 # "☀️"
print(fortune.today_fortune.score)            # 78
print(fortune.today_fortune.overall_analysis) # "오늘은..."

for item in fortune.today_fortune.action_items:
    print(f"{'✓' if item.type == 'do' else '✕'} {item.text}")

stream_daily_fortune

from sajuapi import FortuneStream

stream = client.stream_daily_fortune(
    saju=saju,
    user_name="홍길동"
)

for event in stream:
    if event.type == "character":
        print(f"성격: {event.data.day_master}")
    elif event.type == "tendency":
        print(f"위험 감수성: {event.data.scores.risk_tolerance}")
    elif event.type == "fortune":
        print(f"점수: {event.data.score}")
    elif event.type == "complete":
        print("모든 데이터 로드됨!")

비동기 지원

import asyncio
from sajuapi import AsyncSajuClient

async def main():
    client = AsyncSajuClient(api_key="bs_live_xxx")

    fortune = await client.get_daily_fortune(
        saju=saju,
        user_name="홍길동"
    )

    print(fortune.today_fortune.score)

    await client.close()

asyncio.run(main())

에러 처리

from sajuapi import SajuClientError, RateLimitError, AuthenticationError

try:
    fortune = client.get_daily_fortune(saju=saju, user_name="홍길동")
except RateLimitError as e:
    print(f"요청 제한됨. {e.retry_after}초 후 재시도")
    time.sleep(e.retry_after)
except AuthenticationError as e:
    print(f"인증 에러: {e.message}")
except SajuClientError as e:
    print(f"API 에러 [{e.code}]: {e.message}")
    print(f"요청 ID: {e.request_id}")

데이터 클래스

from sajuapi.types import (
    Saju,
    Pillar,
    FortuneResponse,
    CharacterData,
    TodayFortune,
    ActionItem
)

# 타입 힌트로 IDE 자동완성 지원
def process_fortune(fortune: FortuneResponse) -> None:
    score: int = fortune.today_fortune.score
    items: list[ActionItem] = fortune.today_fortune.action_items

Django 통합

# views.py
from django.http import JsonResponse
from sajuapi import SajuClient, SajuCalculator
from django.conf import settings

client = SajuClient(api_key=settings.SAJU_API_KEY)

def get_fortune(request):
    data = json.loads(request.body)

    saju = SajuCalculator.calculate(
        year=data["year"],
        month=data["month"],
        day=data["day"],
        hour=data.get("hour"),
        gender=data["gender"]
    )

    fortune = client.get_daily_fortune(
        saju=saju,
        user_name=data["userName"]
    )

    return JsonResponse(fortune.to_dict())

FastAPI 통합

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from sajuapi import AsyncSajuClient, SajuCalculator

app = FastAPI()
client = AsyncSajuClient()

class FortuneRequest(BaseModel):
    year: int
    month: int
    day: int
    hour: int | None = None
    gender: str
    user_name: str

@app.post("/fortune")
async def get_fortune(request: FortuneRequest):
    saju = SajuCalculator.calculate(
        year=request.year,
        month=request.month,
        day=request.day,
        hour=request.hour,
        gender=request.gender
    )

    fortune = await client.get_daily_fortune(
        saju=saju,
        user_name=request.user_name
    )

    return fortune.to_dict()

Redis 캐싱

import redis
import json
from datetime import date

redis_client = redis.Redis()

def get_fortune_cached(saju, user_name):
    cache_key = f"fortune:{saju.day_master.stem}:{date.today()}"

    cached = redis_client.get(cache_key)
    if cached:
        return json.loads(cached)

    fortune = client.get_daily_fortune(saju=saju, user_name=user_name)
    redis_client.setex(cache_key, 86400, json.dumps(fortune.to_dict()))

    return fortune