ginipick commited on
Commit
62d25a6
·
verified ·
1 Parent(s): 8a7e52b

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +118 -0
app.py ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import aiohttp
2
+ import asyncio
3
+ from flask import Flask, render_template_string
4
+ from typing import List, Dict, Union
5
+ import base64
6
+
7
+ app = Flask(__name__)
8
+
9
+ async def get_most_liked_spaces(limit: int = 100) -> Union[List[Dict], str]:
10
+ url = "https://huggingface.co/api/spaces"
11
+ params = {
12
+ "sort": "likes",
13
+ "direction": -1,
14
+ "limit": limit,
15
+ "full": "true"
16
+ }
17
+
18
+ async with aiohttp.ClientSession() as session:
19
+ try:
20
+ async with session.get(url, params=params) as response:
21
+ response.raise_for_status()
22
+ data = await response.json()
23
+
24
+ if isinstance(data, list):
25
+ return data
26
+ else:
27
+ return f"Unexpected API response format: {type(data)}"
28
+ except aiohttp.ClientError as e:
29
+ return f"API request error: {str(e)}"
30
+ except ValueError as e:
31
+ return f"JSON decoding error: {str(e)}"
32
+
33
+ async def capture_thumbnail(space_id: str) -> str:
34
+ screenshot_url = f"https://huggingface.co/spaces/{space_id}/screenshot.jpg"
35
+ async with aiohttp.ClientSession() as session:
36
+ try:
37
+ async with session.get(screenshot_url) as response:
38
+ if response.status == 200:
39
+ image_data = await response.read()
40
+ return base64.b64encode(image_data).decode('utf-8')
41
+ except aiohttp.ClientError:
42
+ pass
43
+ return ""
44
+
45
+ async def format_spaces(spaces: Union[List[Dict], str]) -> List[Dict]:
46
+ if isinstance(spaces, str):
47
+ return [{"error": spaces}]
48
+
49
+ formatted_spaces = []
50
+ for space in spaces:
51
+ if not isinstance(space, dict):
52
+ formatted_spaces.append({"error": f"Unexpected space data format: {type(space)}"})
53
+ continue
54
+
55
+ space_id = space.get('id', 'Unknown')
56
+ space_name = space_id.split('/')[-1] if '/' in space_id else space_id
57
+
58
+ space_author = space.get('author', 'Unknown')
59
+ if isinstance(space_author, dict):
60
+ space_author = space_author.get('user', space_author.get('name', 'Unknown'))
61
+
62
+ space_likes = space.get('likes', 'N/A')
63
+ space_url = f"https://huggingface.co/spaces/{space_id}"
64
+
65
+ thumbnail = await capture_thumbnail(space_id)
66
+
67
+ formatted_space = {
68
+ "name": space_name,
69
+ "author": space_author,
70
+ "likes": space_likes,
71
+ "url": space_url,
72
+ "thumbnail": thumbnail
73
+ }
74
+ formatted_spaces.append(formatted_space)
75
+
76
+ return formatted_spaces
77
+
78
+ @app.route('/')
79
+ async def index():
80
+ spaces_list = await get_most_liked_spaces()
81
+ formatted_spaces = await format_spaces(spaces_list)
82
+
83
+ html_template = """
84
+ <!DOCTYPE html>
85
+ <html lang="en">
86
+ <head>
87
+ <meta charset="UTF-8">
88
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
89
+ <title>Hugging Face Most Liked Spaces</title>
90
+ <style>
91
+ body { font-family: Arial, sans-serif; }
92
+ .space-item { margin-bottom: 20px; }
93
+ .space-item img { max-width: 200px; max-height: 200px; }
94
+ </style>
95
+ </head>
96
+ <body>
97
+ <h1>Hugging Face Most Liked Spaces</h1>
98
+ <ol>
99
+ {% for space in spaces %}
100
+ <li class="space-item">
101
+ <a href="{{ space.url }}" target="_blank">
102
+ {{ space.name }} by {{ space.author }} (Likes: {{ space.likes }})
103
+ </a>
104
+ {% if space.thumbnail %}
105
+ <br>
106
+ <img src="data:image/jpeg;base64,{{ space.thumbnail }}" alt="{{ space.name }} thumbnail">
107
+ {% endif %}
108
+ </li>
109
+ {% endfor %}
110
+ </ol>
111
+ </body>
112
+ </html>
113
+ """
114
+
115
+ return render_template_string(html_template, spaces=formatted_spaces)
116
+
117
+ if __name__ == "__main__":
118
+ app.run(host='0.0.0.0', port=7860)