Spaces:
Sleeping
Sleeping
import requests | |
import gradio as gr | |
from datetime import datetime | |
import random | |
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_pastel_color(index): | |
"""Generate unique pastel colors based on index""" | |
pastel_colors = [ | |
'#FFE6E6', # μ°ν λΆν | |
'#FFE6FF', # μ°ν λ³΄λΌ | |
'#E6E6FF', # μ°ν νλ | |
'#E6FFFF', # μ°ν νλ | |
'#E6FFE6', # μ°ν μ΄λ‘ | |
'#FFFFE6', # μ°ν λ Έλ | |
'#FFF0E6', # μ°ν μ£Όν© | |
'#F0E6FF', # μ°ν λΌλ²€λ | |
'#FFE6F0', # μ°ν λ‘μ¦ | |
'#E6FFF0', # μ°ν λ―ΌνΈ | |
'#F0FFE6', # μ°ν λΌμ | |
'#FFE6EB', # μ°ν μ½λ | |
'#E6EBFF', # μ°ν νΌνλΈλ£¨ | |
'#FFE6F5', # μ°ν νν¬ | |
'#E6FFF5', # μ°ν ν°μ½μ΄μ¦ | |
'#F5E6FF', # μ°ν λͺ¨λΈ | |
'#FFE6EC', # μ°ν μ΄λͺ¬ | |
'#E6FFEC', # μ°ν μ€νλ§κ·Έλ¦° | |
'#ECE6FF', # μ°ν ν리μν΄ | |
'#FFE6F7', # μ°ν 맀그λ리μ | |
] | |
return pastel_colors[index % len(pastel_colors)] | |
def get_space_card(space, index): | |
"""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λ³ μ΄λͺ¨μ§ λ° κ΄λ ¨ μ΄λͺ¨μ§ μΈνΈ | |
sdk_emoji_sets = { | |
'gradio': { | |
'main': 'π¨', | |
'related': ['πΌοΈ', 'π', 'πͺ', 'π ', 'π‘', 'π’', 'π―', 'π²', 'π°', 'π³'] | |
}, | |
'streamlit': { | |
'main': 'β‘', | |
'related': ['π«', 'β¨', 'β', 'π', 'π₯', 'β‘', 'π₯', 'π', 'π', 'π'] | |
}, | |
'docker': { | |
'main': 'π³', | |
'related': ['π', 'π', 'π', 'π’', 'β΄οΈ', 'π₯οΈ', 'π ', 'π‘', 'π¦', 'π¬'] | |
}, | |
'static': { | |
'main': 'π', | |
'related': ['π', 'π°', 'π', 'ποΈ', 'π', 'π', 'π', 'π', 'π', 'π'] | |
}, | |
'panel': { | |
'main': 'π', | |
'related': ['π', 'π', 'πΉ', 'π', 'π', 'π', 'πΊοΈ', 'π―', 'π', 'π'] | |
}, | |
'N/A': { | |
'main': 'π§', | |
'related': ['π¨', 'βοΈ', 'π οΈ', 'βοΈ', 'π©', 'βοΈ', 'β‘', 'π', 'π‘', 'π'] | |
} | |
} | |
# SDKμ λ°λ₯Έ μ΄λͺ¨μ§ μ ν | |
sdk_lower = sdk.lower() | |
bg_color = get_pastel_color(index) # μΈλ±μ€ κΈ°λ° μμ μ ν | |
emoji_set = sdk_emoji_sets.get(sdk_lower, sdk_emoji_sets['N/A']) | |
main_emoji = emoji_set['main'] | |
# λλ€νκ² 3κ°μ κ΄λ ¨ μ΄λͺ¨μ§ μ ν | |
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, idx) for idx, space in enumerate(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> | |
""" | |
# Creating the Gradio interface | |
demo = gr.Blocks() | |
with demo: | |
html_output = gr.HTML(value=get_user_spaces()) # μ΄κΈ° λ‘λ μ μ§μ ν¨μ νΈμΆ | |
if __name__ == "__main__": | |
demo.launch() |