|
import requests |
|
import gradio as gr |
|
from datetime import datetime |
|
|
|
USERNAME = "openfree" |
|
|
|
def format_timestamp(timestamp): |
|
if timestamp: |
|
dt = datetime.fromisoformat(timestamp.replace('Z', '+00:00')) |
|
return dt.strftime('%Y-%m-%d %H:%M') |
|
return 'N/A' |
|
|
|
def get_space_card(space): |
|
"""Generate HTML card for a space with colorful design and lots of emojis""" |
|
space_id = space.get('id', '') |
|
space_name = space_id.split('/')[-1] |
|
likes = space.get('likes', 0) |
|
created_at = format_timestamp(space.get('createdAt')) |
|
sdk = space.get('sdk', 'N/A') |
|
|
|
|
|
sdk_emoji_sets = { |
|
'gradio': { |
|
'main': 'π¨', |
|
'related': ['πΌοΈ', 'π', 'πͺ', 'π ', 'π‘', 'π’', 'π―', 'π²', 'π°', 'π³'] |
|
}, |
|
'streamlit': { |
|
'main': 'β‘', |
|
'related': ['π«', 'β¨', 'β', 'π', 'π₯', 'β‘', 'π₯', 'π', 'π', 'π'] |
|
}, |
|
'docker': { |
|
'main': 'π³', |
|
'related': ['π', 'π', 'π', 'π’', 'β΄οΈ', 'π₯οΈ', 'π ', 'π‘', 'π¦', 'π¬'] |
|
}, |
|
'static': { |
|
'main': 'π', |
|
'related': ['π', 'π°', 'π', 'ποΈ', 'π', 'π', 'π', 'π', 'π', 'π'] |
|
}, |
|
'panel': { |
|
'main': 'π', |
|
'related': ['π', 'π', 'πΉ', 'π', 'π', 'π', 'πΊοΈ', 'π―', 'π', 'π'] |
|
}, |
|
'N/A': { |
|
'main': 'π§', |
|
'related': ['π¨', 'βοΈ', 'π οΈ', 'βοΈ', 'π©', 'βοΈ', 'β‘', 'π', 'π‘', 'π'] |
|
} |
|
} |
|
|
|
|
|
bg_colors = { |
|
'gradio': '#FFE6E6', |
|
'streamlit': '#E6FFE6', |
|
'docker': '#E6E6FF', |
|
'static': '#FFE6FF', |
|
'panel': '#FFFFE6', |
|
'N/A': '#E6FFFF' |
|
} |
|
|
|
|
|
sdk_lower = sdk.lower() |
|
bg_color = bg_colors.get(sdk_lower, '#FFFFFF') |
|
emoji_set = sdk_emoji_sets.get(sdk_lower, sdk_emoji_sets['N/A']) |
|
main_emoji = emoji_set['main'] |
|
|
|
|
|
import random |
|
decorative_emojis = random.sample(emoji_set['related'], 3) |
|
|
|
|
|
general_emojis = ['π', 'π«', 'β', 'π', 'β¨', 'π₯', 'π₯', 'π', 'π―', 'π¨', |
|
'π', 'πͺ', 'π’', 'π‘', 'π ', 'πͺ', 'π', 'π¨', 'π―', 'π²'] |
|
random_emojis = random.sample(general_emojis, 3) |
|
|
|
|
|
heart_emoji = 'β€οΈ' if likes > 100 else 'π' if likes > 50 else 'π' if likes > 10 else 'π€' |
|
|
|
return f""" |
|
<div style='border: none; |
|
padding: 25px; |
|
margin: 15px; |
|
border-radius: 20px; |
|
background-color: {bg_color}; |
|
box-shadow: 0 4px 15px rgba(0,0,0,0.1); |
|
transition: all 0.3s ease-in-out; |
|
position: relative; |
|
overflow: hidden;' |
|
onmouseover='this.style.transform="translateY(-5px) scale(1.02)"; this.style.boxShadow="0 8px 25px rgba(0,0,0,0.15)"' |
|
onmouseout='this.style.transform="translateY(0) scale(1)"; this.style.boxShadow="0 4px 15px rgba(0,0,0,0.1)"'> |
|
<div style='position: absolute; top: -15px; right: -15px; font-size: 100px; opacity: 0.1;'> |
|
{main_emoji} |
|
</div> |
|
<div style='position: absolute; top: 10px; right: 10px; font-size: 20px;'> |
|
{decorative_emojis[0]} |
|
</div> |
|
<div style='position: absolute; bottom: 10px; left: 10px; font-size: 20px;'> |
|
{decorative_emojis[1]} |
|
</div> |
|
<div style='position: absolute; top: 50%; right: 10px; font-size: 20px;'> |
|
{decorative_emojis[2]} |
|
</div> |
|
<h3 style='color: #2d2d2d; |
|
margin: 0 0 20px 0; |
|
font-size: 1.4em; |
|
display: flex; |
|
align-items: center; |
|
gap: 10px;'> |
|
<span style='font-size: 1.3em'>{random_emojis[0]}</span> |
|
<a href='https://huggingface.co/spaces/{space_id}' target='_blank' |
|
style='text-decoration: none; color: #2d2d2d;'> |
|
{space_name} |
|
</a> |
|
<span style='font-size: 1.3em'>{random_emojis[1]}</span> |
|
</h3> |
|
<div style='margin: 15px 0; color: #444; background: rgba(255,255,255,0.5); |
|
padding: 15px; border-radius: 12px;'> |
|
<p style='margin: 8px 0;'> |
|
<strong>SDK:</strong> {main_emoji} {sdk} {decorative_emojis[0]} |
|
</p> |
|
<p style='margin: 8px 0;'> |
|
<strong>Created:</strong> π
{created_at} β° |
|
</p> |
|
<p style='margin: 8px 0;'> |
|
<strong>Likes:</strong> {heart_emoji} {likes} {random_emojis[2]} |
|
</p> |
|
</div> |
|
<div style='margin-top: 20px; |
|
display: flex; |
|
justify-content: space-between; |
|
align-items: center;'> |
|
<a href='https://huggingface.co/spaces/{space_id}' target='_blank' |
|
style='background: linear-gradient(45deg, #0084ff, #00a3ff); |
|
color: white; |
|
padding: 10px 20px; |
|
border-radius: 15px; |
|
text-decoration: none; |
|
display: inline-flex; |
|
align-items: center; |
|
gap: 8px; |
|
font-weight: 500; |
|
transition: all 0.3s; |
|
box-shadow: 0 2px 8px rgba(0,132,255,0.3);' |
|
onmouseover='this.style.transform="scale(1.05)"; this.style.boxShadow="0 4px 12px rgba(0,132,255,0.4)"' |
|
onmouseout='this.style.transform="scale(1)"; this.style.boxShadow="0 2px 8px rgba(0,132,255,0.3)"'> |
|
<span>View Space</span> π {random_emojis[0]} |
|
</a> |
|
<span style='color: #666; font-size: 0.9em; opacity: 0.7;'> |
|
π {space_id} {decorative_emojis[2]} |
|
</span> |
|
</div> |
|
</div> |
|
""" |
|
|
|
def get_user_spaces(): |
|
url = f"https://huggingface.co/api/spaces?author={USERNAME}&limit=500" |
|
headers = { |
|
"Accept": "application/json", |
|
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" |
|
} |
|
|
|
try: |
|
response = requests.get(url, headers=headers) |
|
print(f"Status Code: {response.status_code}") |
|
print(f"Response length: {len(response.json()) if response.status_code == 200 else 'N/A'}") |
|
|
|
if response.status_code != 200: |
|
return f"Error: Failed to fetch spaces (Status Code: {response.status_code})" |
|
|
|
spaces_data = response.json() |
|
user_spaces = spaces_data |
|
|
|
if not user_spaces: |
|
return f""" |
|
<div style='padding: 20px; text-align: center; color: #666;'> |
|
<h2>No public Spaces found for user: {USERNAME}</h2> |
|
<p>Try visiting: <a href='https://huggingface.co/{USERNAME}' target='_blank'> |
|
https://huggingface.co/{USERNAME}</a></p> |
|
</div> |
|
""" |
|
|
|
user_spaces.sort(key=lambda x: x.get('likes', 0), reverse=True) |
|
|
|
html_content = f""" |
|
<div style='padding: 20px; background-color: #f5f5f5;'> |
|
<div style='margin-bottom: 20px;'> |
|
<h2 style='color: #333; margin: 0 0 10px 0;'>Spaces by {USERNAME}</h2> |
|
<p style='color: #666; margin: 0;'>Found {len(user_spaces)} public spaces</p> |
|
</div> |
|
<div style=' |
|
display: grid; |
|
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); |
|
gap: 20px; |
|
'> |
|
{"".join(get_space_card(space) for space in user_spaces)} |
|
</div> |
|
</div> |
|
""" |
|
|
|
return html_content |
|
|
|
except Exception as e: |
|
print(f"Error: {str(e)}") |
|
return f""" |
|
<div style='padding: 20px; text-align: center; color: #666;'> |
|
<h2>Error occurred while fetching spaces</h2> |
|
<p>Error details: {str(e)}</p> |
|
<p>Please try again later.</p> |
|
</div> |
|
""" |
|
|
|
|
|
demo = gr.Blocks() |
|
|
|
with demo: |
|
html_output = gr.HTML(value=get_user_spaces()) |
|
|
|
if __name__ == "__main__": |
|
demo.launch() |