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('''
Discover the top 500 trending spaces from the Huggingface