Initialize project

This commit is contained in:
woozu.shin
2026-01-28 15:33:47 +09:00
commit 3fe5424732
43 changed files with 6108 additions and 0 deletions

View File

@@ -0,0 +1,52 @@
import shutil
import time
import os
from pathlib import Path
from apscheduler.schedulers.background import BackgroundScheduler
TEMP_DIR = Path("backend/temp_uploads")
def init_temp_dir():
"""임시 디렉토리 생성 (없으면 생성)"""
if not TEMP_DIR.exists():
TEMP_DIR.mkdir(parents=True, exist_ok=True)
print(f"Created temp directory at: {TEMP_DIR.absolute()}")
def cleanup_old_files(max_age_seconds: int = 600):
"""지정된 시간(기본 10분)보다 오래된 파일/폴더 삭제"""
if not TEMP_DIR.exists():
return
now = time.time()
deleted_count = 0
for item in TEMP_DIR.iterdir():
try:
# 최종 수정 시간 확인
item_mtime = item.stat().st_mtime
if now - item_mtime > max_age_seconds:
if item.is_dir():
shutil.rmtree(item)
else:
item.unlink()
deleted_count += 1
except Exception as e:
print(f"Error deleting {item}: {e}")
if deleted_count > 0:
print(f"Cleaned up {deleted_count} old items from temp directory.")
def cleanup_all():
"""서버 시작 시 모든 임시 파일 삭제"""
if TEMP_DIR.exists():
shutil.rmtree(TEMP_DIR)
init_temp_dir()
print("Cleaned up all temporary files on startup.")
def start_scheduler():
"""백그라운드 스케줄러 시작 (1분마다 정리 작업 실행)"""
scheduler = BackgroundScheduler()
# 10분(600초) 지난 파일 삭제 작업을 1분마다 수행
scheduler.add_job(cleanup_old_files, 'interval', minutes=1, args=[600])
scheduler.start()
return scheduler

View File

@@ -0,0 +1,164 @@
from typing import List, Optional
from pydantic import BaseModel
class ToolMetadata(BaseModel):
id: str
name: str
description: str
category: str
tags: List[str]
type: str # 'client' or 'server'
endpoint: Optional[str] = None # Only for server type
# === 도구 등록소 ===
# 새로운 기능을 추가할 때 여기만 수정하면 검색/메뉴에 자동 반영되도록 구성합니다.
TOOLS_REGISTRY = [
ToolMetadata(
id="url-parser",
name="URL Encoder/Decoder",
description="Encodes or decodes a URL string.",
category="Web",
tags=["url", "encode", "decode", "percent-encoding"],
type="client"
),
ToolMetadata(
id="json-formatter",
name="JSON Formatter",
description="Prettify or minify JSON data.",
category="Data",
tags=["json", "pretty", "minify", "format"],
type="client"
),
ToolMetadata(
id="py-uuid",
name="UUID Generator",
description="Generates UUIDs locally (v1/v4).",
category="Development",
tags=["uuid", "guid", "random", "client-side"],
type="client"
),
ToolMetadata(
id="png-compressor",
name="PNG Compressor",
description="Compress PNG images using pngquant (Lossy, 60-80% reduction).",
category="Image",
tags=["image", "png", "compress", "pngquant", "optimize"],
type="server",
endpoint="/api/tools/png-compress"
),
ToolMetadata(
id="password-generator",
name="Password Generator",
description="Generate secure random passwords locally (Client-side).",
category="Security",
tags=["password", "random", "secure", "generator", "client-side"],
type="client"
),
ToolMetadata(
id="jwt-debugger",
name="JWT Debugger",
description="Decode and inspect JSON Web Tokens.",
category="Security",
tags=["jwt", "token", "decode", "security"],
type="client"
),
ToolMetadata(
id="cron-generator",
name="Cron Schedule Generator",
description="Generate and explain cron expressions.",
category="Utility",
tags=["cron", "schedule", "time", "generator"],
type="client"
),
ToolMetadata(
id="sql-formatter",
name="SQL Formatter",
description="Beautify and format SQL queries.",
category="Formatters",
tags=["sql", "format", "database", "query"],
type="client"
),
ToolMetadata(
id="diff-viewer",
name="Diff Viewer",
description="Compare text and see differences side-by-side.",
category="Text",
tags=["diff", "compare", "text", "code"],
type="client"
),
ToolMetadata(
id="qr-generator",
name="QR Code Generator",
description="Generate QR codes from text or URLs.",
category="Generators",
tags=["qr", "code", "generator", "image"],
type="client"
),
ToolMetadata(
id="base64-encoder",
name="Base64 File Encoder",
description="Convert files to Base64 strings.",
category="Encoders",
tags=["base64", "encode", "file", "image"],
type="client"
),
ToolMetadata(
id="json-converter",
name="JSON Converter",
description="Convert between JSON, CSV, and YAML.",
category="Converters",
tags=["json", "csv", "yaml", "convert"],
type="client"
),
ToolMetadata(
id="regex-tester",
name="Regex Tester",
description="Test regular expressions in real-time.",
category="Text",
tags=["regex", "test", "pattern", "match"],
type="client"
),
ToolMetadata(
id="docker-converter",
name="Docker Converter",
description="Convert between Docker Run and Docker Compose.",
category="DevOps",
tags=["docker", "compose", "convert", "devops"],
type="client"
),
ToolMetadata(
id="mock-data-generator",
name="Mock Data Generator",
description="Generate random user data for testing.",
category="Generators",
tags=["mock", "data", "fake", "generator"],
type="client"
),
ToolMetadata(
id="svg-optimizer",
name="SVG Optimizer",
description="Optimize and minify SVG code.",
category="Image",
tags=["svg", "optimize", "minify", "image"],
type="client"
),
ToolMetadata(
id="video-to-gif",
name="Video to GIF",
description="Convert video clips to GIF format.",
category="Video",
tags=["video", "gif", "convert", "ffmpeg"],
type="server",
endpoint="/api/tools/video/gif"
)
]
def search_tools(query: str = "") -> List[ToolMetadata]:
if not query:
return TOOLS_REGISTRY
q = query.lower()
return [
t for t in TOOLS_REGISTRY
if q in t.name.lower() or q in t.description.lower() or any(q in tag for tag in t.tags)
]