406 lines
9.1 KiB
TypeScript
406 lines
9.1 KiB
TypeScript
// 타겟 페르소나
|
|
export interface TargetPersona {
|
|
persona: string;
|
|
age: {
|
|
min_age: number;
|
|
max_age: number;
|
|
};
|
|
favor_target: string[];
|
|
decision_trigger: string;
|
|
}
|
|
|
|
// 셀링 포인트
|
|
export interface SellingPoint {
|
|
english_category: string;
|
|
korean_category: string;
|
|
description: string;
|
|
score: number;
|
|
}
|
|
|
|
// 마케팅 분석 결과
|
|
export interface MarketingAnalysis {
|
|
brand_identity: {
|
|
location_feature_analysis: string;
|
|
concept_scalability: string;
|
|
};
|
|
market_positioning: {
|
|
category_definition: string;
|
|
core_value: string;
|
|
};
|
|
target_persona: TargetPersona[];
|
|
selling_points: SellingPoint[];
|
|
target_keywords: string[];
|
|
}
|
|
|
|
export interface CrawlingResponse {
|
|
image_list: string[];
|
|
image_count: number;
|
|
m_id: number;
|
|
processed_info: {
|
|
customer_name: string;
|
|
region: string;
|
|
detail_region_info: string;
|
|
};
|
|
marketing_analysis: MarketingAnalysis;
|
|
}
|
|
|
|
// URL 이미지 (서버에서 가져온 이미지)
|
|
export interface UrlImage {
|
|
type: 'url';
|
|
url: string;
|
|
}
|
|
|
|
// 업로드된 파일 이미지
|
|
export interface FileImage {
|
|
type: 'file';
|
|
file: File;
|
|
preview: string; // createObjectURL로 생성된 미리보기 URL
|
|
}
|
|
|
|
export type ImageItem = UrlImage | FileImage;
|
|
|
|
// 가사 생성 요청
|
|
export interface LyricGenerateRequest {
|
|
customer_name: string;
|
|
detail_region_info: string;
|
|
language: string;
|
|
m_id: number;
|
|
region: string;
|
|
task_id: string;
|
|
orientation?: 'vertical' | 'horizontal';
|
|
}
|
|
|
|
// 가사 생성 응답
|
|
export interface LyricGenerateResponse {
|
|
success: boolean;
|
|
task_id: string;
|
|
lyric?: string;
|
|
language?: string;
|
|
prompt_used?: string;
|
|
error_message: string | null;
|
|
}
|
|
|
|
// 가사 상태 조회 응답
|
|
export interface LyricStatusResponse {
|
|
message: string;
|
|
status: 'processing' | 'completed' | 'failed';
|
|
task_id: string;
|
|
lyric?: string;
|
|
error_message?: string | null;
|
|
}
|
|
|
|
// 가사 상세 조회 응답
|
|
export interface LyricDetailResponse {
|
|
id: number;
|
|
task_id: string;
|
|
project_id: number;
|
|
status: string;
|
|
lyric_prompt: string;
|
|
lyric_result: string;
|
|
created_at: string;
|
|
}
|
|
|
|
// 노래 생성 요청
|
|
export interface SongGenerateRequest {
|
|
genre: string;
|
|
language: string;
|
|
lyrics: string;
|
|
}
|
|
|
|
// 노래 생성 응답
|
|
export interface SongGenerateResponse {
|
|
success: boolean;
|
|
task_id: string;
|
|
song_id: string;
|
|
message: string;
|
|
error_message: string | null;
|
|
}
|
|
|
|
// 노래 상태 조회 응답 (Suno Polling)
|
|
export interface SongStatusResponse {
|
|
success: boolean;
|
|
status: string;
|
|
message: string;
|
|
song_result_url: string | null;
|
|
error_message: string | null;
|
|
}
|
|
|
|
// 노래 다운로드 상태 조회 응답 (DB Polling)
|
|
export interface SongDownloadResponse {
|
|
success: boolean;
|
|
status: string;
|
|
message: string;
|
|
store_name: string;
|
|
region: string;
|
|
detail_region_info: string;
|
|
task_id: string;
|
|
language: string;
|
|
song_result_url: string;
|
|
created_at: string;
|
|
error_message: string | null;
|
|
}
|
|
|
|
// 영상 생성 응답
|
|
export interface VideoGenerateResponse {
|
|
success: boolean;
|
|
task_id: string;
|
|
creatomate_render_id: string
|
|
message: string;
|
|
error_message: string | null;
|
|
}
|
|
|
|
// 영상 상태 확인 응답
|
|
export interface VideoStatusResponse {
|
|
success: boolean;
|
|
status: string;
|
|
message: string;
|
|
render_data: {
|
|
id: string;
|
|
status: string;
|
|
url: string | null;
|
|
snapshot_url: string | null;
|
|
video_id?: number;
|
|
} | null;
|
|
raw_response?: Record<string, unknown>;
|
|
error_message: string | null;
|
|
}
|
|
|
|
// 영상 다운로드(결과 조회) 응답
|
|
export interface VideoDownloadResponse {
|
|
success: boolean;
|
|
status: string;
|
|
message: string;
|
|
store_name: string;
|
|
region: string;
|
|
task_id: string;
|
|
result_movie_url: string | null;
|
|
created_at: string;
|
|
error_message: string | null;
|
|
}
|
|
|
|
// 이미지 업로드 요청용 URL 이미지 정보
|
|
export interface ImageUrlItem {
|
|
url: string;
|
|
name?: string;
|
|
}
|
|
|
|
// 이미지 업로드 응답
|
|
export interface ImageUploadResponse {
|
|
task_id: string;
|
|
file_count: number;
|
|
image_urls: string[];
|
|
images: Array<{
|
|
id: number;
|
|
img_name: string;
|
|
img_order: number;
|
|
img_url: string;
|
|
source: string;
|
|
}>;
|
|
}
|
|
|
|
// 언어 매핑
|
|
export const LANGUAGE_MAP: Record<string, string> = {
|
|
'한국어': 'Korean',
|
|
'English': 'English',
|
|
'中文': 'Chinese',
|
|
'日本語': 'Japanese',
|
|
'ไทย': 'Thai',
|
|
'Tiếng Việt': 'Vietnamese',
|
|
};
|
|
|
|
// 카카오 로그인 URL 응답
|
|
export interface KakaoLoginUrlResponse {
|
|
auth_url: string;
|
|
}
|
|
|
|
// 카카오 콜백 사용자 정보
|
|
export interface KakaoCallbackUser {
|
|
id: number;
|
|
nickname: string;
|
|
email: string | null;
|
|
profile_image_url: string | null;
|
|
is_new_user: boolean;
|
|
}
|
|
|
|
// 카카오 콜백 응답 (JWT 토큰)
|
|
export interface KakaoCallbackResponse {
|
|
access_token: string;
|
|
refresh_token: string;
|
|
token_type: string;
|
|
expires_in: number;
|
|
user: KakaoCallbackUser;
|
|
redirect_url: string;
|
|
}
|
|
|
|
// 토큰 갱신 응답
|
|
export interface TokenRefreshResponse {
|
|
access_token: string;
|
|
refresh_token: string;
|
|
token_type: string;
|
|
expires_in: number;
|
|
}
|
|
|
|
// 사용자 정보 응답
|
|
export interface UserMeResponse {
|
|
id: number;
|
|
kakao_id: string;
|
|
email?: string;
|
|
nickname: string;
|
|
profile_image_url: string | null;
|
|
thumbnail_image_url?: string | null;
|
|
is_active?: boolean;
|
|
is_admin?: boolean;
|
|
last_login_at?: string;
|
|
created_at: string;
|
|
}
|
|
|
|
export interface UserCreditsResponse {
|
|
credits: number;
|
|
}
|
|
|
|
// 비디오 목록 아이템
|
|
export interface VideoListItem {
|
|
video_id: number;
|
|
store_name: string;
|
|
region: string;
|
|
task_id: string;
|
|
result_movie_url: string;
|
|
created_at: string;
|
|
}
|
|
|
|
// 비디오 목록 응답
|
|
export interface VideosListResponse {
|
|
items: VideoListItem[];
|
|
total: number;
|
|
page: number;
|
|
page_size: number;
|
|
total_pages: number;
|
|
has_next: boolean;
|
|
has_prev: boolean;
|
|
}
|
|
|
|
// ============================================
|
|
// Social OAuth Types
|
|
// ============================================
|
|
|
|
// YouTube OAuth 연결 응답
|
|
export interface YouTubeConnectResponse {
|
|
auth_url: string;
|
|
}
|
|
|
|
// 연결된 소셜 계정 정보 (서버 응답 형식)
|
|
export interface SocialAccount {
|
|
id: number;
|
|
platform: 'youtube' | 'instagram' | 'facebook';
|
|
platform_user_id: string;
|
|
platform_username: string;
|
|
display_name: string;
|
|
is_active: boolean;
|
|
connected_at: string;
|
|
// OAuth 콜백에서 전달받는 추가 정보 (optional)
|
|
profile_image?: string | null;
|
|
}
|
|
|
|
// 소셜 계정 목록 응답
|
|
export interface SocialAccountsResponse {
|
|
accounts: SocialAccount[];
|
|
total: number;
|
|
}
|
|
|
|
// 소셜 계정 단일 조회 응답
|
|
export interface SocialAccountResponse {
|
|
account: SocialAccount | null;
|
|
connected: boolean;
|
|
}
|
|
|
|
// 소셜 계정 연결 해제 응답
|
|
export interface SocialDisconnectResponse {
|
|
success: boolean;
|
|
message: string;
|
|
}
|
|
|
|
// ============================================
|
|
// Social Upload Types (YouTube Upload)
|
|
// ============================================
|
|
|
|
// 유튜브 SEO Description 자동완성 요청
|
|
export interface YTAutoSeoRequest {
|
|
task_id: string; // 아카이브의 비디오 ID
|
|
}
|
|
|
|
// 유튜브 SEO Description 자동완성 응답
|
|
export interface YTAutoSeoResponse {
|
|
title: string;
|
|
description: string;
|
|
keywords: string[];
|
|
}
|
|
|
|
// 소셜 업로드 요청
|
|
export interface SocialUploadRequest {
|
|
video_id: number; // 아카이브의 비디오 ID
|
|
social_account_id: number; // 선택된 채널 ID
|
|
title: string; // 최대 100자
|
|
description: string; // 최대 5000자
|
|
tags: string[]; // 태그 배열
|
|
privacy_status: 'public' | 'unlisted' | 'private'; // 공개 범위
|
|
scheduled_at: string | null; // ISO 형식 또는 null (즉시 게시)
|
|
}
|
|
|
|
// 소셜 업로드 응답
|
|
export interface SocialUploadResponse {
|
|
success: boolean;
|
|
upload_id: string;
|
|
status: 'pending' | 'uploading' | 'completed' | 'failed';
|
|
message: string;
|
|
}
|
|
|
|
// 소셜 업로드 상태 조회 응답
|
|
export interface SocialUploadStatusResponse {
|
|
success: boolean;
|
|
upload_id: number;
|
|
video_id: number;
|
|
platform: string;
|
|
status: 'pending' | 'uploading' | 'completed' | 'failed';
|
|
upload_progress: number; // 업로드 진행률 (0-100)
|
|
title?: string; // 영상 제목
|
|
platform_video_id?: string; // 완료 시 플랫폼 비디오 ID
|
|
platform_url?: string; // 완료 시 플랫폼 URL
|
|
error_message?: string | null; // 실패 시 에러 메시지
|
|
retry_count?: number;
|
|
created_at?: string;
|
|
uploaded_at?: string;
|
|
}
|
|
|
|
// 업로드 히스토리 아이템
|
|
export interface UploadHistoryItem {
|
|
upload_id: number;
|
|
video_id: number;
|
|
platform: string;
|
|
status: 'pending' | 'uploading' | 'completed' | 'failed' | 'scheduled' | 'cancelled';
|
|
title: string;
|
|
channel_name: string;
|
|
scheduled_at: string | null;
|
|
uploaded_at: string | null;
|
|
created_at: string;
|
|
platform_url: string | null;
|
|
error_message: string | null;
|
|
}
|
|
|
|
// 업로드 히스토리 응답
|
|
export interface UploadHistoryResponse {
|
|
success: boolean;
|
|
items: UploadHistoryItem[];
|
|
total?: number;
|
|
page?: number;
|
|
size?: number;
|
|
}
|
|
|
|
// Social OAuth 토큰 만료 에러 응답
|
|
export interface TokenExpiredErrorResponse {
|
|
detail: string;
|
|
code: 'TOKEN_EXPIRED';
|
|
platform: string;
|
|
reconnect_url: string;
|
|
}
|
|
|