Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -12,7 +12,7 @@ def fetch_trending_spaces(offset=0, limit=72):
|
|
| 12 |
try:
|
| 13 |
# Simple data fetching
|
| 14 |
url = "https://huggingface.co/api/spaces"
|
| 15 |
-
params = {"limit":
|
| 16 |
|
| 17 |
# Increase timeout
|
| 18 |
response = requests.get(url, params=params, timeout=30)
|
|
@@ -206,8 +206,7 @@ if __name__ == '__main__':
|
|
| 206 |
|
| 207 |
# Create index.html file
|
| 208 |
with open('templates/index.html', 'w', encoding='utf-8') as f:
|
| 209 |
-
f.write('''
|
| 210 |
-
<!DOCTYPE html>
|
| 211 |
<html lang="en">
|
| 212 |
<head>
|
| 213 |
<meta charset="UTF-8">
|
|
@@ -527,9 +526,12 @@ if __name__ == '__main__':
|
|
| 527 |
position: relative;
|
| 528 |
}
|
| 529 |
|
|
|
|
| 530 |
.grid-content iframe {
|
| 531 |
-
|
| 532 |
-
|
|
|
|
|
|
|
| 533 |
border: none;
|
| 534 |
border-radius: 0;
|
| 535 |
}
|
|
@@ -550,17 +552,18 @@ if __name__ == '__main__':
|
|
| 550 |
}
|
| 551 |
|
| 552 |
.error-emoji {
|
| 553 |
-
font-size:
|
| 554 |
-
margin-bottom:
|
| 555 |
animation: bounce 1s infinite alternate;
|
|
|
|
| 556 |
}
|
| 557 |
|
| 558 |
@keyframes bounce {
|
| 559 |
from {
|
| 560 |
-
transform: translateY(0px);
|
| 561 |
}
|
| 562 |
to {
|
| 563 |
-
transform: translateY(-
|
| 564 |
}
|
| 565 |
}
|
| 566 |
|
|
@@ -730,6 +733,14 @@ if __name__ == '__main__':
|
|
| 730 |
height: 300px;
|
| 731 |
}
|
| 732 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 733 |
</style>
|
| 734 |
</head>
|
| 735 |
<body>
|
|
@@ -825,7 +836,123 @@ if __name__ == '__main__':
|
|
| 825 |
staticModeAttempted: {}, // Track which spaces have attempted static mode
|
| 826 |
statsVisible: false,
|
| 827 |
chartInstance: null,
|
| 828 |
-
topOwners: []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 829 |
};
|
| 830 |
|
| 831 |
// Random emoji list for 404 errors
|
|
@@ -852,90 +979,7 @@ if __name__ == '__main__':
|
|
| 852 |
'🍱', '🍘', '🍙', '🍚', '🍛', '🍜', '🍝', '🍠', '🍢', '🍣',
|
| 853 |
'🍤', '🍥', '🥮', '🍡', '🥟', '🥠', '🥡', '🦀', '🦞', '🦐',
|
| 854 |
'🦑', '🦪', '🍦', '🍧', '🍨', '🍩', '🍪', '🎂', '🍰', '🧁',
|
| 855 |
-
'🥧', '🍫', '🍬', '🍭', '🍮', '🍯', '🍼', '🥛', '☕', '🍵'
|
| 856 |
-
'🍶', '🍾', '🍷', '🍸', '🍹', '🍺', '🍻', '🥂', '🥃', '🥤',
|
| 857 |
-
'🧃', '🧉', '🧊', '🥢', '🍽️', '🍴', '🥄', '🔪', '🏺', '🌍',
|
| 858 |
-
'🌎', '🌏', '🌐', '🗺️', '🗾', '🧭', '🏔️', '⛰️', '🌋', '🗻',
|
| 859 |
-
'🏕️', '🏖️', '🏜️', '🏝️', '🏞️', '🏟️', '🏛️', '🏗️', '🧱', '🏘️',
|
| 860 |
-
'🏚️', '🏠', '🏡', '🏢', '🏣', '🏤', '🏥', '🏦', '🏨', '🏩',
|
| 861 |
-
'🏪', '🏫', '🏬', '🏭', '🏯', '🏰', '💒', '🗼', '🗽', '⛪',
|
| 862 |
-
'🕌', '🛕', '🕍', '⛩️', '🕋', '⛲', '⛺', '🌁', '🌃', '🏙️',
|
| 863 |
-
'🌄', '🌅', '🌆', '🌇', '🌉', '♨️', '🎠', '🎡', '🎢', '💈',
|
| 864 |
-
'🎪', '🚂', '🚃', '🚄', '🚅', '🚆', '🚇', '🚈', '🚉', '🚊',
|
| 865 |
-
'🚝', '🚞', '🚋', '🚌', '🚍', '🚎', '🚐', '🚑', '🚒', '🚓',
|
| 866 |
-
'🚔', '🚕', '🚖', '🚗', '🚘', '🚙', '🚚', '🚛', '🚜', '🏎️',
|
| 867 |
-
'🏍️', '🛵', '🦽', '🦼', '🛺', '🚲', '🛴', '🛹', '🚏', '🛣️',
|
| 868 |
-
'🛤️', '🛢️', '⛽', '🚨', '🚥', '🚦', '🛑', '🚧', '⚓', '⛵',
|
| 869 |
-
'🛶', '🚤', '🛳️', '⛴️', '🛥️', '🚢', '✈️', '🛩️', '🛫', '🛬',
|
| 870 |
-
'🪂', '💺', '🚁', '🚟', '🚠', '🚡', '🛰️', '🚀', '🛸', '🛎️',
|
| 871 |
-
'🧳', '⌛', '⏳', '⌚', '⏰', '⏱️', '⏲️', '🕰️', '🕛', '🕧',
|
| 872 |
-
'🕐', '🕜', '🕑', '🕝', '🕒', '🕞', '🕓', '🕟', '🕔', '🕠',
|
| 873 |
-
'🕕', '🕡', '🕖', '🕢', '🕗', '🕣', '🕘', '🕤', '🕙', '🕥',
|
| 874 |
-
'🕚', '🕦', '🌑', '🌒', '🌓', '🌔', '🌕', '🌖', '🌗', '🌘',
|
| 875 |
-
'🌙', '🌚', '🌛', '🌜', '🌡️', '☀️', '🌝', '🌞', '🪐', '⭐',
|
| 876 |
-
'🌟', '🌠', '🌌', '☁️', '⛅', '⛈️', '🌤️', '🌥️', '🌦️', '🌧️',
|
| 877 |
-
'🌨️', '🌩️', '🌪️', '🌫️', '🌬️', '🌀', '🌈', '🌂', '☂️', '☔',
|
| 878 |
-
'⛱️', '⚡', '❄️', '☃️', '⛄', '☄️', '🔥', '💧', '🌊', '🎃',
|
| 879 |
-
'🎄', '🎆', '🎇', '🧨', '✨', '🎈', '🎉', '🎊', '🎋', '🎍',
|
| 880 |
-
'🎎', '🎏', '🎐', '🎑', '🧧', '🎀', '🎁', '🎗️', '🎟️', '🎫',
|
| 881 |
-
'🎖️', '🏆', '🏅', '🥇', '🥈', '🥉', '⚽', '⚾', '🥎', '🏀',
|
| 882 |
-
'🏐', '🏈', '🏉', '🎾', '🥏', '🎳', '🏏', '🏑', '🏒', '🥍',
|
| 883 |
-
'🏓', '🏸', '🥊', '🥋', '🥅', '⛳', '⛸️', '🎣', '🤿', '🎽',
|
| 884 |
-
'🎿', '🛷', '🥌', '🎯', '🪀', '🪁', '🎱', '🔮', '🧿', '🎮',
|
| 885 |
-
'🕹️', '🎰', '🎲', '🧩', '🧸', '♠️', '♥️', '♦️', '♣️', '♟️',
|
| 886 |
-
'🃏', '🀄', '🎴', '🎭', '🖼️', '🎨', '🧵', '🧶', '👓', '🕶️',
|
| 887 |
-
'🥽', '🥼', '🦺', '👔', '👕', '👖', '🧣', '🧤', '🧥', '🧦',
|
| 888 |
-
'👗', '👘', '🥻', '🩱', '🩲', '🩳', '👙', '👚', '👛', '👜',
|
| 889 |
-
'👝', '🛍️', '🎒', '👞', '👟', '🥾', '🥿', '👠', '👡', '🩰',
|
| 890 |
-
'👢', '👑', '👒', '🎩', '🎓', '🧢', '⛑️', '📿', '💄', '💍',
|
| 891 |
-
'💎', '🔇', '🔈', '🔉', '🔊', '📢', '📣', '📯', '🔔', '🔕',
|
| 892 |
-
'🎼', '🎵', '🎶', '🎙️', '🎚️', '🎛️', '🎤', '🎧', '📻', '🎷',
|
| 893 |
-
'🎸', '🎹', '🎺', '🎻', '🪕', '🥁', '📱', '📲', '☎️', '📞',
|
| 894 |
-
'📟', '📠', '🔋', '🔌', '💻', '🖥️', '🖨️', '⌨️', '🖱️', '🖲️',
|
| 895 |
-
'💽', '💾', '💿', '📀', '🧮', '🎥', '🎞️', '📽️', '🎬', '📺',
|
| 896 |
-
'📷', '📸', '📹', '📼', '🔍', '🔎', '🕯️', '💡', '🔦', '🏮',
|
| 897 |
-
'🪔', '📔', '📕', '📖', '📗', '📘', '📙', '📚', '📓', '📒',
|
| 898 |
-
'📃', '📜', '📄', '📰', '🗞️', '📑', '🔖', '🏷️', '💰', '💴',
|
| 899 |
-
'💵', '💶', '💷', '💸', '💳', '🧾', '💹', '✉️', '📧', '📨',
|
| 900 |
-
'📩', '📤', '📥', '📦', '📫', '📪', '📬', '📭', '📮', '🗳️',
|
| 901 |
-
'✏️', '✒️', '🖋️', '🖊️', '🖌️', '🖍️', '📝', '💼', '📁', '📂',
|
| 902 |
-
'🗂️', '📅', '📆', '🗒️', '🗓️', '📇', '📈', '📉', '📊', '📋',
|
| 903 |
-
'📌', '📍', '📎', '🖇️', '📏', '📐', '✂️', '🗃️', '🗄️', '🗑️',
|
| 904 |
-
'🔒', '🔓', '🔏', '🔐', '🔑', '🗝️', '🔨', '🪓', '⛏️', '⚒️',
|
| 905 |
-
'🛠️', '🗡️', '⚔️', '🔫', '🏹', '🛡️', '🔧', '🔩', '⚙️', '🗜️',
|
| 906 |
-
'⚖️', '🦯', '🔗', '⛓️', '🧰', '🧲', '⚗️', '🧪', '🧫', '🧬',
|
| 907 |
-
'🔬', '🔭', '📡', '💉', '🩸', '💊', '🩹', '🩺', '🚪', '🛏️',
|
| 908 |
-
'🛋️', '🪑', '🚽', '🚿', '🛁', '🪒', '🧴', '🧷', '🧹', '🧺',
|
| 909 |
-
'🧻', '🧼', '🧽', '🧯', '🛒', '🚬', '⚰️', '⚱️', '🗿', '🏧',
|
| 910 |
-
'🚮', '🚰', '♿', '🚹', '🚺', '🚻', '🚼', '🚾', '🛂', '🛃',
|
| 911 |
-
'🛄', '🛅', '⚠️', '🚸', '⛔', '🚫', '🚳', '🚭', '🚯', '🚱',
|
| 912 |
-
'🚷', '📵', '🔞', '☢️', '☣️', '⬆️', '↗️', '➡️', '↘️', '⬇️',
|
| 913 |
-
'↙️', '⬅️', '↖️', '↕️', '↔️', '↩️', '↪️', '⤴️', '⤵️', '🔃',
|
| 914 |
-
'🔄', '🔙', '🔚', '🔛', '🔜', '🔝', '🛐', '⚛️', '🕉️', '✡️',
|
| 915 |
-
'☸️', '☯️', '✝️', '☦️', '☪️', '☮️', '🕎', '🔯', '♈', '♉',
|
| 916 |
-
'♊', '♋', '♌', '♍', '♎', '♏', '♐', '♑', '♒', '♓', '⛎',
|
| 917 |
-
'🔀', '🔁', '🔂', '▶️', '⏩', '⏭️', '⏯️', '◀️', '⏪', '⏮️',
|
| 918 |
-
'🔼', '⏫', '🔽', '⏬', '⏸️', '⏹️', '⏺️', '⏏️', '🎦', '🔅',
|
| 919 |
-
'🔆', '📶', '📳', '📴', '♀️', '♂️', '⚧️', '✖️', '➕', '➖',
|
| 920 |
-
'➗', '♾️', '‼️', '⁉️', '❓', '❔', '❕', '❗', '〰️', '💱',
|
| 921 |
-
'💲', '⚕️', '♻️', '⚜️', '🔱', '📛', '🔰', '⭕', '✅', '☑️',
|
| 922 |
-
'✔️', '❌', '❎', '➰', '➿', '〽️', '✳️', '✴️', '❇️', '©️',
|
| 923 |
-
'®️', '™️', '#️⃣', '*️⃣', '0️⃣', '1️⃣', '2️⃣', '3️⃣', '4️⃣', '5️⃣',
|
| 924 |
-
'6️⃣', '7️⃣', '8️⃣', '9️⃣', '🔟', '🔠', '🔡', '🔢', '🔣', '🔤',
|
| 925 |
-
'🅰️', '🆎', '🅱️', '🆑', '🆒', '🆓', 'ℹ️', '🆔', 'Ⓜ️', '🆕',
|
| 926 |
-
'🆖', '🅾️', '🆗', '🅿️', '🆘', '🆙', '🆚', '🈁', '🈂️', '🈷️',
|
| 927 |
-
'🈶', '🈯', '🉐', '🈹', '🈚', '🈲', '🉑', '🈸', '🈴', '🈳',
|
| 928 |
-
'㊗️', '㊙️', '🈺', '🈵', '🔴', '🟠', '🟡', '🟢', '🔵', '🟣',
|
| 929 |
-
'🟤', '⚫', '⚪', '🟥', '🟧', '🟨', '🟩', '🟦', '🟪', '🟫',
|
| 930 |
-
'⬛', '⬜', '◼️', '◻️', '◾', '◽', '▪️', '▫️', '🔶', '🔷',
|
| 931 |
-
'🔸', '🔹', '🔺', '🔻', '💠', '🔘', '🔳', '🔲', '🏁', '🚩',
|
| 932 |
-
'🎌', '🏴', '🏳️', '🏳️🌈', '🏴☠️', '🇦🇨', '🇦🇩', '🇦🇪', '🇦🇫', '🇦🇬',
|
| 933 |
-
'🇦🇮', '🇦🇱', '🇦🇲', '🇦🇴', '🇦🇶', '🇦🇷', '🇦🇸', '🇦🇹', '🇦🇺', '🇦🇼',
|
| 934 |
-
'🇦🇽', '🇦🇿', '🇧🇦', '🇧🇧', '🇧🇩', '🇧🇪', '🇧🇫', '🇧🇬', '🇧🇭', '🇧🇮',
|
| 935 |
-
'🇧🇯', '🇧🇱', '🇧🇲', '🇧🇳', '🇧🇴', '🇧🇶', '🇧🇷', '🇧🇸', '🇧🇹', '🇧🇻',
|
| 936 |
-
'🇧🇼', '🇧🇾', '🇧🇿', '🇨🇦', '🇨🇨', '🇨🇩', '🇨🇫', '🇨🇬', '🇨🇭', '🇨🇮',
|
| 937 |
-
'🇨🇰', '🇨🇱', '🇨🇲', '🇨🇳', '🇨🇴', '🇨🇵', '🇨🇷', '🇨🇺', '🇨🇻', '🇨🇼',
|
| 938 |
-
'🇨🇽', '🇨🇾', '🇨🇿'
|
| 939 |
];
|
| 940 |
|
| 941 |
// Display loading indicator
|
|
@@ -1063,6 +1107,17 @@ if __name__ == '__main__':
|
|
| 1063 |
title: {
|
| 1064 |
display: true,
|
| 1065 |
text: 'Creator ID'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1066 |
}
|
| 1067 |
}
|
| 1068 |
}
|
|
@@ -1199,21 +1254,6 @@ if __name__ == '__main__':
|
|
| 1199 |
errorMessage.textContent = `"${title}" space couldn't be loaded`;
|
| 1200 |
errorPlaceholder.appendChild(errorMessage);
|
| 1201 |
|
| 1202 |
-
// Try static site version button
|
| 1203 |
-
const directStaticLink = document.createElement('a');
|
| 1204 |
-
directStaticLink.href = `https://${owner}-${name}.hf.space/index.html`;
|
| 1205 |
-
directStaticLink.target = '_blank';
|
| 1206 |
-
directStaticLink.textContent = 'Try Static Version';
|
| 1207 |
-
directStaticLink.style.color = '#3182ce';
|
| 1208 |
-
directStaticLink.style.marginTop = '10px';
|
| 1209 |
-
directStaticLink.style.display = 'inline-block';
|
| 1210 |
-
directStaticLink.style.padding = '8px 16px';
|
| 1211 |
-
directStaticLink.style.background = '#ebf8ff';
|
| 1212 |
-
directStaticLink.style.borderRadius = '5px';
|
| 1213 |
-
directStaticLink.style.fontWeight = '600';
|
| 1214 |
-
directStaticLink.style.marginRight = '10px';
|
| 1215 |
-
errorPlaceholder.appendChild(directStaticLink);
|
| 1216 |
-
|
| 1217 |
// Direct HF link
|
| 1218 |
const directLink = document.createElement('a');
|
| 1219 |
directLink.href = `https://huggingface.co/spaces/${owner}/${name}`;
|
|
@@ -1323,59 +1363,34 @@ if __name__ == '__main__':
|
|
| 1323 |
iframe.setAttribute('frameborder', '0');
|
| 1324 |
iframe.loading = 'lazy'; // Lazy load iframes for better performance
|
| 1325 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1326 |
// Track this space
|
| 1327 |
const spaceKey = `${owner}/${name}`;
|
| 1328 |
-
state.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1329 |
|
| 1330 |
-
//
|
| 1331 |
iframe.onerror = function() {
|
| 1332 |
-
|
| 1333 |
-
|
| 1334 |
-
state.staticModeAttempted[spaceKey] = true;
|
| 1335 |
-
iframe.src = directUrl + '/index.html';
|
| 1336 |
-
} else {
|
| 1337 |
-
// If static mode also failed, show error with random emoji
|
| 1338 |
-
handleIframeError(iframe, owner, name, title);
|
| 1339 |
-
}
|
| 1340 |
};
|
| 1341 |
|
| 1342 |
-
//
|
| 1343 |
-
|
| 1344 |
-
|
| 1345 |
-
|
| 1346 |
-
|
| 1347 |
-
// Check if we got a 404 page or other error by looking for certain elements
|
| 1348 |
-
const isErrorPage = iframeDoc.title.includes('404') ||
|
| 1349 |
-
iframeDoc.body.textContent.includes('404') ||
|
| 1350 |
-
iframeDoc.body.textContent.includes('not found');
|
| 1351 |
-
|
| 1352 |
-
if (isErrorPage) {
|
| 1353 |
-
// For 404 errors, show random emoji
|
| 1354 |
-
if (!state.staticModeAttempted[spaceKey]) {
|
| 1355 |
-
// Try static mode first
|
| 1356 |
-
state.staticModeAttempted[spaceKey] = true;
|
| 1357 |
-
iframe.src = directUrl + '/index.html';
|
| 1358 |
-
} else {
|
| 1359 |
-
// If static mode already attempted and still failing, show random emoji
|
| 1360 |
-
handleIframeError(iframe, owner, name, title);
|
| 1361 |
-
}
|
| 1362 |
-
}
|
| 1363 |
-
} catch (e) {
|
| 1364 |
-
// Cross-origin errors are expected, this generally means the iframe loaded
|
| 1365 |
-
// If we need to check for static mode, we do it based on other signals
|
| 1366 |
-
|
| 1367 |
-
// We can try detecting failed loads by using a timer and checking if the iframe content is visible
|
| 1368 |
-
setTimeout(() => {
|
| 1369 |
-
// This is a basic heuristic - if the iframe still has no visible content after 5s, try static mode
|
| 1370 |
-
if (!state.staticModeAttempted[spaceKey] &&
|
| 1371 |
-
(iframe.clientHeight < 10 || iframe.clientWidth < 10)) {
|
| 1372 |
-
state.staticModeAttempted[spaceKey] = true;
|
| 1373 |
-
iframe.src = directUrl + '/index.html';
|
| 1374 |
-
}
|
| 1375 |
-
}, 5000);
|
| 1376 |
}
|
| 1377 |
-
};
|
| 1378 |
|
|
|
|
| 1379 |
iframeContainer.appendChild(iframe);
|
| 1380 |
content.appendChild(iframeContainer);
|
| 1381 |
|
|
@@ -1463,4 +1478,4 @@ if __name__ == '__main__':
|
|
| 1463 |
''')
|
| 1464 |
|
| 1465 |
# Use port 7860 for Huggingface Spaces
|
| 1466 |
-
app.run(host='0.0.0.0', port=7860)
|
|
|
|
| 12 |
try:
|
| 13 |
# Simple data fetching
|
| 14 |
url = "https://huggingface.co/api/spaces"
|
| 15 |
+
params = {"limit": 10000} # Get max 10000 to fetch more spaces
|
| 16 |
|
| 17 |
# Increase timeout
|
| 18 |
response = requests.get(url, params=params, timeout=30)
|
|
|
|
| 206 |
|
| 207 |
# Create index.html file
|
| 208 |
with open('templates/index.html', 'w', encoding='utf-8') as f:
|
| 209 |
+
f.write('''<!DOCTYPE html>
|
|
|
|
| 210 |
<html lang="en">
|
| 211 |
<head>
|
| 212 |
<meta charset="UTF-8">
|
|
|
|
| 526 |
position: relative;
|
| 527 |
}
|
| 528 |
|
| 529 |
+
/* Apply 70% scaling to iframes */
|
| 530 |
.grid-content iframe {
|
| 531 |
+
transform: scale(0.7);
|
| 532 |
+
transform-origin: top left;
|
| 533 |
+
width: 142.857%;
|
| 534 |
+
height: 142.857%;
|
| 535 |
border: none;
|
| 536 |
border-radius: 0;
|
| 537 |
}
|
|
|
|
| 552 |
}
|
| 553 |
|
| 554 |
.error-emoji {
|
| 555 |
+
font-size: 6rem;
|
| 556 |
+
margin-bottom: 1.5rem;
|
| 557 |
animation: bounce 1s infinite alternate;
|
| 558 |
+
text-shadow: 0 10px 20px rgba(0,0,0,0.1);
|
| 559 |
}
|
| 560 |
|
| 561 |
@keyframes bounce {
|
| 562 |
from {
|
| 563 |
+
transform: translateY(0px) scale(1);
|
| 564 |
}
|
| 565 |
to {
|
| 566 |
+
transform: translateY(-15px) scale(1.1);
|
| 567 |
}
|
| 568 |
}
|
| 569 |
|
|
|
|
| 733 |
height: 300px;
|
| 734 |
}
|
| 735 |
}
|
| 736 |
+
|
| 737 |
+
.error-emoji-detector {
|
| 738 |
+
position: fixed;
|
| 739 |
+
top: -9999px;
|
| 740 |
+
left: -9999px;
|
| 741 |
+
z-index: -1;
|
| 742 |
+
opacity: 0;
|
| 743 |
+
}
|
| 744 |
</style>
|
| 745 |
</head>
|
| 746 |
<body>
|
|
|
|
| 836 |
staticModeAttempted: {}, // Track which spaces have attempted static mode
|
| 837 |
statsVisible: false,
|
| 838 |
chartInstance: null,
|
| 839 |
+
topOwners: [],
|
| 840 |
+
iframeStatuses: {} // Track iframe loading status
|
| 841 |
+
};
|
| 842 |
+
|
| 843 |
+
// Advanced iframe loader for better error detection
|
| 844 |
+
const iframeLoader = {
|
| 845 |
+
checkQueue: {},
|
| 846 |
+
maxAttempts: 5, // Try multiple times
|
| 847 |
+
checkInterval: 5000, // Check every 5 seconds
|
| 848 |
+
|
| 849 |
+
// Start checking iframe loading status
|
| 850 |
+
startChecking: function(iframe, owner, name, title, spaceKey) {
|
| 851 |
+
// Initialize tracking
|
| 852 |
+
this.checkQueue[spaceKey] = {
|
| 853 |
+
iframe: iframe,
|
| 854 |
+
owner: owner,
|
| 855 |
+
name: name,
|
| 856 |
+
title: title,
|
| 857 |
+
attempts: 0,
|
| 858 |
+
status: 'loading'
|
| 859 |
+
};
|
| 860 |
+
|
| 861 |
+
// Start recursive checking
|
| 862 |
+
this.checkIframeStatus(spaceKey);
|
| 863 |
+
},
|
| 864 |
+
|
| 865 |
+
// Check iframe loading status
|
| 866 |
+
checkIframeStatus: function(spaceKey) {
|
| 867 |
+
if (!this.checkQueue[spaceKey]) return;
|
| 868 |
+
|
| 869 |
+
const item = this.checkQueue[spaceKey];
|
| 870 |
+
const iframe = item.iframe;
|
| 871 |
+
|
| 872 |
+
// If already processed, stop checking
|
| 873 |
+
if (item.status !== 'loading') {
|
| 874 |
+
delete this.checkQueue[spaceKey];
|
| 875 |
+
return;
|
| 876 |
+
}
|
| 877 |
+
|
| 878 |
+
// Increment attempt counter
|
| 879 |
+
item.attempts++;
|
| 880 |
+
|
| 881 |
+
try {
|
| 882 |
+
// 1. Check if iframe was removed from DOM
|
| 883 |
+
if (!iframe || !iframe.parentNode) {
|
| 884 |
+
delete this.checkQueue[spaceKey];
|
| 885 |
+
return;
|
| 886 |
+
}
|
| 887 |
+
|
| 888 |
+
// 2. Check if content has loaded
|
| 889 |
+
try {
|
| 890 |
+
const hasContent = iframe.contentWindow &&
|
| 891 |
+
iframe.contentWindow.document &&
|
| 892 |
+
iframe.contentWindow.document.body;
|
| 893 |
+
|
| 894 |
+
// 2.1 If content exists and has actual content loaded
|
| 895 |
+
if (hasContent && iframe.contentWindow.document.body.innerHTML.length > 100) {
|
| 896 |
+
// Check if it contains error text
|
| 897 |
+
const bodyText = iframe.contentWindow.document.body.textContent.toLowerCase();
|
| 898 |
+
if (bodyText.includes('forbidden') ||
|
| 899 |
+
bodyText.includes('404') ||
|
| 900 |
+
bodyText.includes('not found') ||
|
| 901 |
+
bodyText.includes('error')) {
|
| 902 |
+
item.status = 'error';
|
| 903 |
+
handleIframeError(iframe, item.owner, item.name, item.title);
|
| 904 |
+
} else {
|
| 905 |
+
item.status = 'success';
|
| 906 |
+
}
|
| 907 |
+
delete this.checkQueue[spaceKey];
|
| 908 |
+
return;
|
| 909 |
+
}
|
| 910 |
+
} catch(e) {
|
| 911 |
+
// Cross-origin access errors are expected - might be normal loading
|
| 912 |
+
}
|
| 913 |
+
|
| 914 |
+
// 3. Check iframe's visible size
|
| 915 |
+
const rect = iframe.getBoundingClientRect();
|
| 916 |
+
if (rect.width > 50 && rect.height > 50 && item.attempts > 2) {
|
| 917 |
+
// If it has sufficient size, mark as success
|
| 918 |
+
item.status = 'success';
|
| 919 |
+
delete this.checkQueue[spaceKey];
|
| 920 |
+
return;
|
| 921 |
+
}
|
| 922 |
+
|
| 923 |
+
// 4. If we've reached max attempts
|
| 924 |
+
if (item.attempts >= this.maxAttempts) {
|
| 925 |
+
// Final check: is iframe visible?
|
| 926 |
+
if (iframe.offsetWidth > 0 && iframe.offsetHeight > 0) {
|
| 927 |
+
// If visible, mark as success
|
| 928 |
+
item.status = 'success';
|
| 929 |
+
} else {
|
| 930 |
+
// If still not visible, mark as error
|
| 931 |
+
item.status = 'error';
|
| 932 |
+
handleIframeError(iframe, item.owner, item.name, item.title);
|
| 933 |
+
}
|
| 934 |
+
delete this.checkQueue[spaceKey];
|
| 935 |
+
return;
|
| 936 |
+
}
|
| 937 |
+
|
| 938 |
+
// Schedule next check with exponential backoff
|
| 939 |
+
const nextDelay = this.checkInterval * Math.pow(1.5, item.attempts - 1);
|
| 940 |
+
setTimeout(() => this.checkIframeStatus(spaceKey), nextDelay);
|
| 941 |
+
|
| 942 |
+
} catch (e) {
|
| 943 |
+
console.error('Error checking iframe status:', e);
|
| 944 |
+
|
| 945 |
+
// If error occurs, try a few more times
|
| 946 |
+
if (item.attempts >= this.maxAttempts) {
|
| 947 |
+
item.status = 'error';
|
| 948 |
+
handleIframeError(iframe, item.owner, item.name, item.title);
|
| 949 |
+
delete this.checkQueue[spaceKey];
|
| 950 |
+
} else {
|
| 951 |
+
// Try again
|
| 952 |
+
setTimeout(() => this.checkIframeStatus(spaceKey), this.checkInterval);
|
| 953 |
+
}
|
| 954 |
+
}
|
| 955 |
+
}
|
| 956 |
};
|
| 957 |
|
| 958 |
// Random emoji list for 404 errors
|
|
|
|
| 979 |
'🍱', '🍘', '🍙', '🍚', '🍛', '🍜', '🍝', '🍠', '🍢', '🍣',
|
| 980 |
'🍤', '🍥', '🥮', '🍡', '🥟', '🥠', '🥡', '🦀', '🦞', '🦐',
|
| 981 |
'🦑', '🦪', '🍦', '🍧', '🍨', '🍩', '🍪', '🎂', '🍰', '🧁',
|
| 982 |
+
'🥧', '🍫', '🍬', '🍭', '🍮', '🍯', '🍼', '🥛', '☕', '🍵'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 983 |
];
|
| 984 |
|
| 985 |
// Display loading indicator
|
|
|
|
| 1107 |
title: {
|
| 1108 |
display: true,
|
| 1109 |
text: 'Creator ID'
|
| 1110 |
+
},
|
| 1111 |
+
// Ensure all labels are shown without gaps
|
| 1112 |
+
ticks: {
|
| 1113 |
+
autoSkip: false,
|
| 1114 |
+
font: function(context) {
|
| 1115 |
+
// Adjust font size to fit all labels if needed
|
| 1116 |
+
const defaultSize = 11;
|
| 1117 |
+
return {
|
| 1118 |
+
size: labels.length > 20 ? defaultSize - 1 : defaultSize
|
| 1119 |
+
};
|
| 1120 |
+
}
|
| 1121 |
}
|
| 1122 |
}
|
| 1123 |
}
|
|
|
|
| 1254 |
errorMessage.textContent = `"${title}" space couldn't be loaded`;
|
| 1255 |
errorPlaceholder.appendChild(errorMessage);
|
| 1256 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1257 |
// Direct HF link
|
| 1258 |
const directLink = document.createElement('a');
|
| 1259 |
directLink.href = `https://huggingface.co/spaces/${owner}/${name}`;
|
|
|
|
| 1363 |
iframe.setAttribute('frameborder', '0');
|
| 1364 |
iframe.loading = 'lazy'; // Lazy load iframes for better performance
|
| 1365 |
|
| 1366 |
+
// Unique ID for this iframe
|
| 1367 |
+
const iframeId = `iframe-${owner}-${name}`;
|
| 1368 |
+
iframe.id = iframeId;
|
| 1369 |
+
|
| 1370 |
// Track this space
|
| 1371 |
const spaceKey = `${owner}/${name}`;
|
| 1372 |
+
state.iframeStatuses[spaceKey] = 'loading';
|
| 1373 |
+
|
| 1374 |
+
// Use the advanced loader for better error detection
|
| 1375 |
+
iframe.onload = function() {
|
| 1376 |
+
iframeLoader.startChecking(iframe, owner, name, title, spaceKey);
|
| 1377 |
+
};
|
| 1378 |
|
| 1379 |
+
// Direct error handling
|
| 1380 |
iframe.onerror = function() {
|
| 1381 |
+
handleIframeError(iframe, owner, name, title);
|
| 1382 |
+
state.iframeStatuses[spaceKey] = 'error';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1383 |
};
|
| 1384 |
|
| 1385 |
+
// Final fallback - if nothing has happened after 30 seconds, show error
|
| 1386 |
+
setTimeout(() => {
|
| 1387 |
+
if (state.iframeStatuses[spaceKey] === 'loading') {
|
| 1388 |
+
handleIframeError(iframe, owner, name, title);
|
| 1389 |
+
state.iframeStatuses[spaceKey] = 'error';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1390 |
}
|
| 1391 |
+
}, 30000);
|
| 1392 |
|
| 1393 |
+
// Add iframe to container
|
| 1394 |
iframeContainer.appendChild(iframe);
|
| 1395 |
content.appendChild(iframeContainer);
|
| 1396 |
|
|
|
|
| 1478 |
''')
|
| 1479 |
|
| 1480 |
# Use port 7860 for Huggingface Spaces
|
| 1481 |
+
app.run(host='0.0.0.0', port=7860)
|