from flask import Flask, render_template, request, jsonify import requests import os import time import random from collections import Counter app = Flask(__name__) # Function to fetch trending spaces from Huggingface with pagination def fetch_trending_spaces(offset=0, limit=72): try: # Simple data fetching url = "https://huggingface.co/api/spaces" params = {"limit": 10000} # Get max 10000 to fetch more spaces # Increase timeout response = requests.get(url, params=params, timeout=30) if response.status_code == 200: spaces = response.json() filtered_spaces = [space for space in spaces if space.get('owner') != 'None' and space.get('id', '').split('/', 1)[0] != 'None'] # Slice according to requested offset and limit start = min(offset, len(filtered_spaces)) end = min(offset + limit, len(filtered_spaces)) print(f"Fetched {len(filtered_spaces)} spaces, returning {end-start} items from {start} to {end}") return { 'spaces': filtered_spaces[start:end], 'total': len(filtered_spaces), 'offset': offset, 'limit': limit, 'all_spaces': filtered_spaces # Return all spaces for stats calculation } else: print(f"Error fetching spaces: {response.status_code}") # Return empty spaces with fake 200 limit data return { 'spaces': generate_dummy_spaces(limit), 'total': 200, 'offset': offset, 'limit': limit, 'all_spaces': generate_dummy_spaces(500) # Dummy data for stats } except Exception as e: print(f"Exception when fetching spaces: {e}") # Generate fake data return { 'spaces': generate_dummy_spaces(limit), 'total': 200, 'offset': offset, 'limit': limit, 'all_spaces': generate_dummy_spaces(500) # Dummy data for stats } # Generate dummy spaces in case of error def generate_dummy_spaces(count): spaces = [] for i in range(count): spaces.append({ 'id': f'dummy/space-{i}', 'owner': 'dummy', 'title': f'Example Space {i+1}', 'likes': 100 - i, 'createdAt': '2023-01-01T00:00:00.000Z' }) return spaces # Transform Huggingface URL to direct space URL def transform_url(owner, name): # 1. Replace '.' with '-' name = name.replace('.', '-') # 2. Replace '_' with '-' name = name.replace('_', '-') # 3. Convert to lowercase owner = owner.lower() name = name.lower() return f"https://{owner}-{name}.hf.space" # Get space details def get_space_details(space_data, index, offset): try: # Extract common info if '/' in space_data.get('id', ''): owner, name = space_data.get('id', '').split('/', 1) else: owner = space_data.get('owner', '') name = space_data.get('id', '') # Ignore if contains None if owner == 'None' or name == 'None': return None # Construct URLs original_url = f"https://huggingface.co/spaces/{owner}/{name}" embed_url = transform_url(owner, name) # Likes count likes_count = space_data.get('likes', 0) # Extract title title = space_data.get('title', name) # Tags tags = space_data.get('tags', []) return { 'url': original_url, 'embedUrl': embed_url, 'title': title, 'owner': owner, 'name': name, # Store Space name 'likes_count': likes_count, 'tags': tags, 'rank': offset + index + 1 } except Exception as e: print(f"Error processing space data: {e}") # Return basic object even if error occurs return { 'url': 'https://huggingface.co/spaces', 'embedUrl': 'https://huggingface.co/spaces', 'title': 'Error Loading Space', 'owner': 'huggingface', 'name': 'error', 'likes_count': 0, 'tags': [], 'rank': offset + index + 1 } # Get owner statistics from all spaces def get_owner_stats(all_spaces): owners = [] for space in all_spaces: if '/' in space.get('id', ''): owner, _ = space.get('id', '').split('/', 1) else: owner = space.get('owner', '') if owner != 'None': owners.append(owner) # Count occurrences of each owner owner_counts = Counter(owners) # Get top 30 owners by count top_owners = owner_counts.most_common(30) return top_owners # Homepage route @app.route('/') def home(): return render_template('index.html') # Trending spaces API @app.route('/api/trending-spaces', methods=['GET']) def trending_spaces(): search_query = request.args.get('search', '').lower() offset = int(request.args.get('offset', 0)) limit = int(request.args.get('limit', 72)) # Default 72 # Fetch trending spaces spaces_data = fetch_trending_spaces(offset, limit) # Process and filter spaces results = [] for index, space_data in enumerate(spaces_data['spaces']): space_info = get_space_details(space_data, index, offset) if not space_info: continue # Apply search filter if needed if search_query: title = space_info['title'].lower() owner = space_info['owner'].lower() url = space_info['url'].lower() tags = ' '.join([str(tag) for tag in space_info.get('tags', [])]).lower() if (search_query not in title and search_query not in owner and search_query not in url and search_query not in tags): continue results.append(space_info) # Get owner statistics for all spaces top_owners = get_owner_stats(spaces_data.get('all_spaces', [])) return jsonify({ 'spaces': results, 'total': spaces_data['total'], 'offset': offset, 'limit': limit, 'top_owners': top_owners # Add top owners data }) if __name__ == '__main__': # Create templates folder os.makedirs('templates', exist_ok=True) # Create index.html file with open('templates/index.html', 'w', encoding='utf-8') as f: f.write(''' Huggingface Spaces Gallery
Huggingface Explorer

HF Space Leaderboard

Discover the top 500 trending spaces from the Huggingface

Creator Statistics
Top 30 Creators by Number of Spaces
Loading amazing spaces...
If this takes too long, try refreshing the page.
''') # Use port 7860 for Huggingface Spaces app.run(host='0.0.0.0', port=7860)