import requests import concurrent.futures from flask import Flask, render_template_string, jsonify from typing import List, Dict, Union import base64 import os app = Flask(__name__) # 환경 변수에서 토큰 가져오기 HF_TOKEN = os.getenv("HF_TOKEN") def get_headers(): if not HF_TOKEN: raise ValueError("Hugging Face token not found in environment variables") return {"Authorization": f"Bearer {HF_TOKEN}"} def get_most_liked_spaces(limit: int = 100) -> Union[List[Dict], str]: url = "https://huggingface.co/api/spaces" params = { "sort": "likes", "direction": -1, "limit": limit, "full": "true" } try: response = requests.get(url, params=params, headers=get_headers()) response.raise_for_status() data = response.json() if isinstance(data, list): return data else: return f"Unexpected API response format: {type(data)}" except requests.RequestException as e: return f"API request error: {str(e)}" except ValueError as e: return f"JSON decoding error: {str(e)}" def capture_thumbnail(space_id: str) -> str: screenshot_url = f"https://huggingface.co/spaces/{space_id}/screenshot.jpg" try: response = requests.get(screenshot_url, headers=get_headers()) if response.status_code == 200: return base64.b64encode(response.content).decode('utf-8') except requests.RequestException: pass return "" def get_app_py_content(space_id: str) -> str: app_py_url = f"https://huggingface.co/spaces/{space_id}/raw/main/app.py" try: response = requests.get(app_py_url, headers=get_headers()) if response.status_code == 200: return response.text else: return f"app.py file not found or inaccessible for space: {space_id}" except requests.RequestException: return f"Error fetching app.py content for space: {space_id}" def format_space(space: Dict) -> Dict: space_id = space.get('id', 'Unknown') space_name = space_id.split('/')[-1] if '/' in space_id else space_id space_author = space.get('author', 'Unknown') if isinstance(space_author, dict): space_author = space_author.get('user', space_author.get('name', 'Unknown')) space_likes = space.get('likes', 'N/A') space_url = f"https://huggingface.co/spaces/{space_id}" thumbnail = capture_thumbnail(space_id) return { "id": space_id, "name": space_name, "author": space_author, "likes": space_likes, "url": space_url, "thumbnail": thumbnail } def format_spaces(spaces: Union[List[Dict], str]) -> List[Dict]: if isinstance(spaces, str): return [{"error": spaces}] with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor: return list(executor.map(format_space, spaces)) @app.route('/') def index(): try: spaces_list = get_most_liked_spaces() formatted_spaces = format_spaces(spaces_list) except ValueError as e: return str(e), 500 html_template = """