내부 youtube 업로드 endpoint 적용 .
parent
fa8ce3d071
commit
7a887153ab
|
|
@ -0,0 +1,43 @@
|
||||||
|
"""
|
||||||
|
내부 전용 소셜 업로드 API
|
||||||
|
|
||||||
|
스케줄러 서버에서만 호출하는 내부 엔드포인트입니다.
|
||||||
|
X-Internal-Secret 헤더로 인증합니다.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from fastapi import APIRouter, BackgroundTasks, Header, HTTPException, status
|
||||||
|
|
||||||
|
from app.social.worker.upload_task import process_social_upload
|
||||||
|
from config import internal_settings
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
router = APIRouter(prefix="/internal/social", tags=["Internal"])
|
||||||
|
|
||||||
|
|
||||||
|
def _verify_secret(x_internal_secret: str = Header(...)) -> None:
|
||||||
|
if x_internal_secret != internal_settings.INTERNAL_SECRET_KEY:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_403_FORBIDDEN,
|
||||||
|
detail="Invalid internal secret",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post(
|
||||||
|
"/upload/{upload_id}",
|
||||||
|
summary="[내부] 예약 업로드 실행",
|
||||||
|
description="스케줄러 서버에서 호출하는 내부 전용 엔드포인트입니다.",
|
||||||
|
)
|
||||||
|
async def trigger_scheduled_upload(
|
||||||
|
upload_id: int,
|
||||||
|
background_tasks: BackgroundTasks,
|
||||||
|
x_internal_secret: str = Header(...),
|
||||||
|
) -> dict:
|
||||||
|
_verify_secret(x_internal_secret)
|
||||||
|
|
||||||
|
logger.info(f"[INTERNAL] 예약 업로드 실행 - upload_id: {upload_id}")
|
||||||
|
background_tasks.add_task(process_social_upload, upload_id)
|
||||||
|
|
||||||
|
return {"success": True, "upload_id": upload_id, "message": "업로드 작업이 시작되었습니다."}
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
소셜 미디어 영상 업로드 관련 엔드포인트를 제공합니다.
|
소셜 미디어 영상 업로드 관련 엔드포인트를 제공합니다.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import logging, json
|
import logging
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from fastapi import APIRouter, BackgroundTasks, Depends, Query
|
from fastapi import APIRouter, BackgroundTasks, Depends, Query
|
||||||
|
|
@ -158,6 +158,7 @@ async def upload_to_social(
|
||||||
description=body.description,
|
description=body.description,
|
||||||
tags=body.tags,
|
tags=body.tags,
|
||||||
privacy_status=body.privacy_status.value,
|
privacy_status=body.privacy_status.value,
|
||||||
|
scheduled_at=body.scheduled_at,
|
||||||
platform_options={
|
platform_options={
|
||||||
**(body.platform_options or {}),
|
**(body.platform_options or {}),
|
||||||
"scheduled_at": body.scheduled_at.isoformat() if body.scheduled_at else None,
|
"scheduled_at": body.scheduled_at.isoformat() if body.scheduled_at else None,
|
||||||
|
|
@ -175,15 +176,19 @@ async def upload_to_social(
|
||||||
f"account_id: {account.id}, upload_seq: {next_seq}, platform: {account.platform}"
|
f"account_id: {account.id}, upload_seq: {next_seq}, platform: {account.platform}"
|
||||||
)
|
)
|
||||||
|
|
||||||
# 6. 백그라운드 태스크 등록
|
# 6. 백그라운드 태스크 등록 (즉시 업로드 or 예약 없을 때만)
|
||||||
|
from app.utils.timezone import now as utcnow
|
||||||
|
is_scheduled = body.scheduled_at and body.scheduled_at > utcnow()
|
||||||
|
if not is_scheduled:
|
||||||
background_tasks.add_task(process_social_upload, social_upload.id)
|
background_tasks.add_task(process_social_upload, social_upload.id)
|
||||||
|
|
||||||
|
message = "예약 업로드가 등록되었습니다." if is_scheduled else "업로드 요청이 접수되었습니다."
|
||||||
return SocialUploadResponse(
|
return SocialUploadResponse(
|
||||||
success=True,
|
success=True,
|
||||||
upload_id=social_upload.id,
|
upload_id=social_upload.id,
|
||||||
platform=account.platform,
|
platform=account.platform,
|
||||||
status=social_upload.status,
|
status=social_upload.status,
|
||||||
message="업로드 요청이 접수되었습니다.",
|
message=message,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -190,6 +190,15 @@ class SocialUpload(Base):
|
||||||
comment="플랫폼별 추가 옵션 (JSON)",
|
comment="플랫폼별 추가 옵션 (JSON)",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# ==========================================================================
|
||||||
|
# 예약 게시 시간
|
||||||
|
# ==========================================================================
|
||||||
|
scheduled_at: Mapped[Optional[datetime]] = mapped_column(
|
||||||
|
DateTime,
|
||||||
|
nullable=True,
|
||||||
|
comment="예약 게시 시간 (스케줄러가 이 시간 이후에 업로드 실행)",
|
||||||
|
)
|
||||||
|
|
||||||
# ==========================================================================
|
# ==========================================================================
|
||||||
# 에러 정보
|
# 에러 정보
|
||||||
# ==========================================================================
|
# ==========================================================================
|
||||||
|
|
|
||||||
12
config.py
12
config.py
|
|
@ -566,6 +566,17 @@ class SocialOAuthSettings(BaseSettings):
|
||||||
model_config = _base_config
|
model_config = _base_config
|
||||||
|
|
||||||
|
|
||||||
|
class InternalSettings(BaseSettings):
|
||||||
|
"""내부 서버 간 통신 설정"""
|
||||||
|
|
||||||
|
INTERNAL_SECRET_KEY: str = Field(
|
||||||
|
default="change-me-internal-secret-key",
|
||||||
|
description="스케줄러 서버 → 백엔드 내부 API 인증 키",
|
||||||
|
)
|
||||||
|
|
||||||
|
model_config = _base_config
|
||||||
|
|
||||||
|
|
||||||
class SocialUploadSettings(BaseSettings):
|
class SocialUploadSettings(BaseSettings):
|
||||||
"""소셜 미디어 업로드 설정
|
"""소셜 미디어 업로드 설정
|
||||||
|
|
||||||
|
|
@ -613,4 +624,5 @@ kakao_settings = KakaoSettings()
|
||||||
jwt_settings = JWTSettings()
|
jwt_settings = JWTSettings()
|
||||||
recovery_settings = RecoverySettings()
|
recovery_settings = RecoverySettings()
|
||||||
social_oauth_settings = SocialOAuthSettings()
|
social_oauth_settings = SocialOAuthSettings()
|
||||||
|
internal_settings = InternalSettings()
|
||||||
social_upload_settings = SocialUploadSettings()
|
social_upload_settings = SocialUploadSettings()
|
||||||
|
|
|
||||||
2
main.py
2
main.py
|
|
@ -22,6 +22,7 @@ from app.video.api.routers.v1.video import router as video_router
|
||||||
from app.social.api.routers.v1.oauth import router as social_oauth_router
|
from app.social.api.routers.v1.oauth import router as social_oauth_router
|
||||||
from app.social.api.routers.v1.upload import router as social_upload_router
|
from app.social.api.routers.v1.upload import router as social_upload_router
|
||||||
from app.social.api.routers.v1.seo import router as social_seo_router
|
from app.social.api.routers.v1.seo import router as social_seo_router
|
||||||
|
from app.social.api.routers.v1.internal import router as social_internal_router
|
||||||
from app.utils.cors import CustomCORSMiddleware
|
from app.utils.cors import CustomCORSMiddleware
|
||||||
from config import prj_settings
|
from config import prj_settings
|
||||||
|
|
||||||
|
|
@ -362,6 +363,7 @@ app.include_router(archive_router) # Archive API 라우터 추가
|
||||||
app.include_router(social_oauth_router, prefix="/social") # Social OAuth 라우터 추가
|
app.include_router(social_oauth_router, prefix="/social") # Social OAuth 라우터 추가
|
||||||
app.include_router(social_upload_router, prefix="/social") # Social Upload 라우터 추가
|
app.include_router(social_upload_router, prefix="/social") # Social Upload 라우터 추가
|
||||||
app.include_router(social_seo_router, prefix="/social") # Social Upload 라우터 추가
|
app.include_router(social_seo_router, prefix="/social") # Social Upload 라우터 추가
|
||||||
|
app.include_router(social_internal_router) # 내부 스케줄러 전용 라우터
|
||||||
app.include_router(sns_router) # SNS API 라우터 추가
|
app.include_router(sns_router) # SNS API 라우터 추가
|
||||||
|
|
||||||
# DEBUG 모드에서만 테스트 라우터 등록
|
# DEBUG 모드에서만 테스트 라우터 등록
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue