openfree commited on
Commit
2b1a603
โ€ข
1 Parent(s): bf292f3

Delete app-backup.py

Browse files
Files changed (1) hide show
  1. app-backup.py +0 -838
app-backup.py DELETED
@@ -1,838 +0,0 @@
1
- import requests
2
- import gradio as gr
3
- from datetime import datetime
4
- import random
5
- from selenium import webdriver
6
- from selenium.webdriver.support.ui import WebDriverWait
7
- from selenium.webdriver.support import expected_conditions as EC
8
- from selenium.webdriver.common.by import By
9
- from selenium.common.exceptions import WebDriverException, TimeoutException
10
- from PIL import Image
11
- from io import BytesIO
12
- import base64
13
- import time
14
-
15
- def take_screenshot(url):
16
- """์›น์‚ฌ์ดํŠธ ์Šคํฌ๋ฆฐ์ƒท ์ดฌ์˜ ํ•จ์ˆ˜ (๋กœ๋”ฉ ๋Œ€๊ธฐ ์‹œ๊ฐ„ ์ถ”๊ฐ€)"""
17
- if not url.startswith('http'):
18
- url = f"https://{url}"
19
-
20
- options = webdriver.ChromeOptions()
21
- options.add_argument('--headless')
22
- options.add_argument('--no-sandbox')
23
- options.add_argument('--disable-dev-shm-usage')
24
- options.add_argument('--window-size=1080,720')
25
-
26
- try:
27
- driver = webdriver.Chrome(options=options)
28
- driver.get(url)
29
-
30
- # ๋ช…์‹œ์  ๋Œ€๊ธฐ: body ์š”์†Œ๊ฐ€ ๋กœ๋“œ๋  ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐ (์ตœ๋Œ€ 10์ดˆ)
31
- try:
32
- WebDriverWait(driver, 10).until(
33
- EC.presence_of_element_located((By.TAG_NAME, "body"))
34
- )
35
- except TimeoutException:
36
- print(f"ํŽ˜์ด์ง€ ๋กœ๋”ฉ ํƒ€์ž„์•„์›ƒ: {url}")
37
-
38
- # ์ถ”๊ฐ€ ๋Œ€๊ธฐ ์‹œ๊ฐ„ (1์ดˆ)
39
- time.sleep(1)
40
-
41
- # JavaScript ์‹คํ–‰ ์™„๋ฃŒ ๋Œ€๊ธฐ
42
- driver.execute_script("return document.readyState") == "complete"
43
-
44
- # ์Šคํฌ๋ฆฐ์ƒท ์ดฌ์˜
45
- screenshot = driver.get_screenshot_as_png()
46
- img = Image.open(BytesIO(screenshot))
47
- buffered = BytesIO()
48
- img.save(buffered, format="PNG")
49
- return base64.b64encode(buffered.getvalue()).decode()
50
-
51
- except WebDriverException as e:
52
- print(f"์Šคํฌ๋ฆฐ์ƒท ์ดฌ์˜ ์‹คํŒจ: {str(e)} for URL: {url}")
53
- return None
54
- except Exception as e:
55
- print(f"์˜ˆ์ƒ์น˜ ๋ชปํ•œ ์˜ค๋ฅ˜: {str(e)} for URL: {url}")
56
- return None
57
- finally:
58
- if 'driver' in locals():
59
- driver.quit()
60
-
61
- USERNAME = "openfree"
62
-
63
- def format_timestamp(timestamp):
64
- if not timestamp:
65
- return 'N/A'
66
- try:
67
- # ๋ฌธ์ž์—ด์ธ ๊ฒฝ์šฐ
68
- if isinstance(timestamp, str):
69
- dt = datetime.fromisoformat(timestamp.replace('Z', '+00:00'))
70
- # ์ •์ˆ˜(๋ฐ€๋ฆฌ์ดˆ)์ธ ๊ฒฝ์šฐ
71
- elif isinstance(timestamp, (int, float)):
72
- dt = datetime.fromtimestamp(timestamp / 1000) # ๋ฐ€๋ฆฌ์ดˆ๋ฅผ ์ดˆ๋กœ ๋ณ€ํ™˜
73
- else:
74
- return 'N/A'
75
- return dt.strftime('%Y-%m-%d %H:%M')
76
- except Exception as e:
77
- print(f"Timestamp conversion error: {str(e)} for timestamp: {timestamp}")
78
- return 'N/A'
79
-
80
-
81
- def should_exclude_space(space_name):
82
- """ํŠน์ • ์ŠคํŽ˜์ด์Šค๋ฅผ ์ œ์™ธํ•˜๋Š” ํ•„ํ„ฐ ํ•จ์ˆ˜"""
83
- exclude_keywords = [
84
- 'mixgen3', 'ginid', 'mouse', 'flxtrainlora',
85
- 'vidslicegpu', 'stickimg', 'ultpixgen', 'SORA',
86
- 'badassgi', 'newsplus', 'chargen', 'news',
87
- 'testhtml'
88
- ]
89
-
90
- return any(keyword.lower() in space_name.lower() for keyword in exclude_keywords)
91
-
92
- def get_pastel_color(index):
93
- """Generate unique pastel colors based on index"""
94
- pastel_colors = [
95
- '#FFE6E6', # ์—ฐํ•œ ๋ถ„ํ™
96
- '#FFE6FF', # ์—ฐํ•œ ๋ณด๋ผ
97
- '#E6E6FF', # ์—ฐํ•œ ํŒŒ๋ž‘
98
- '#E6FFFF', # ์—ฐํ•œ ํ•˜๋Š˜
99
- '#E6FFE6', # ์—ฐํ•œ ์ดˆ๋ก
100
- '#FFFFE6', # ์—ฐํ•œ ๋…ธ๋ž‘
101
- '#FFF0E6', # ์—ฐํ•œ ์ฃผํ™ฉ
102
- '#F0E6FF', # ์—ฐํ•œ ๋ผ๋ฒค๋”
103
- '#FFE6F0', # ์—ฐํ•œ ๋กœ์ฆˆ
104
- '#E6FFF0', # ์—ฐํ•œ ๋ฏผํŠธ
105
- '#F0FFE6', # ์—ฐํ•œ ๋ผ์ž„
106
- '#FFE6EB', # ์—ฐํ•œ ์ฝ”๋ž„
107
- '#E6EBFF', # ์—ฐํ•œ ํผํ”Œ๋ธ”๋ฃจ
108
- '#FFE6F5', # ์—ฐํ•œ ํ•‘ํฌ
109
- '#E6FFF5', # ์—ฐํ•œ ํ„ฐ์ฝ”์ด์ฆˆ
110
- '#F5E6FF', # ์—ฐํ•œ ๋ชจ๋ธŒ
111
- '#FFE6EC', # ์—ฐํ•œ ์‚ด๋ชฌ
112
- '#E6FFEC', # ์—ฐํ•œ ์Šคํ”„๋ง๊ทธ๋ฆฐ
113
- '#ECE6FF', # ์—ฐํ•œ ํŽ˜๋ฆฌ์œ™ํด
114
- '#FFE6F7', # ์—ฐํ•œ ๋งค๊ทธ๋†€๋ฆฌ์•„
115
- ]
116
- return pastel_colors[index % len(pastel_colors)]
117
-
118
- def get_space_card(space, index):
119
- """Generate HTML card for a space with colorful design and lots of emojis"""
120
- space_id = space.get('id', '')
121
- space_name = space_id.split('/')[-1]
122
- likes = space.get('likes', 0)
123
- created_at = format_timestamp(space.get('createdAt'))
124
- sdk = space.get('sdk', 'N/A')
125
-
126
- # SDK๋ณ„ ์ด๋ชจ์ง€ ๋ฐ ๊ด€๋ จ ์ด๋ชจ์ง€ ์„ธํŠธ
127
- sdk_emoji_sets = {
128
- 'gradio': {
129
- 'main': '๐ŸŽจ',
130
- 'related': ['๐Ÿ–ผ๏ธ', '๐ŸŽญ', '๐ŸŽช', '๐ŸŽ ', '๐ŸŽก', '๐ŸŽข', '๐ŸŽฏ', '๐ŸŽฒ', '๐ŸŽฐ', '๐ŸŽณ']
131
- },
132
- 'streamlit': {
133
- 'main': 'โšก',
134
- 'related': ['๐Ÿ’ซ', 'โœจ', 'โญ', '๐ŸŒŸ', '๐Ÿ’ฅ', 'โšก', '๐Ÿ”ฅ', '๐ŸŒˆ', '๐ŸŽ†', '๐ŸŽ‡']
135
- },
136
- 'docker': {
137
- 'main': '๐Ÿณ',
138
- 'related': ['๐Ÿ‹', '๐ŸŒŠ', '๐ŸŒ', '๐Ÿšข', 'โ›ด๏ธ', '๐Ÿ›ฅ๏ธ', '๐Ÿ ', '๐Ÿก', '๐Ÿฆˆ', '๐Ÿฌ']
139
- },
140
- 'static': {
141
- 'main': '๐Ÿ“„',
142
- 'related': ['๐Ÿ“', '๐Ÿ“ฐ', '๐Ÿ“‘', '๐Ÿ—‚๏ธ', '๐Ÿ“', '๐Ÿ“‚', '๐Ÿ“š', '๐Ÿ“–', '๐Ÿ“’', '๐Ÿ“”']
143
- },
144
- 'panel': {
145
- 'main': '๐Ÿ“Š',
146
- 'related': ['๐Ÿ“ˆ', '๐Ÿ“‰', '๐Ÿ’น', '๐Ÿ“‹', '๐Ÿ“Œ', '๐Ÿ“', '๐Ÿ—บ๏ธ', '๐ŸŽฏ', '๐Ÿ“', '๐Ÿ“']
147
- },
148
- 'N/A': {
149
- 'main': '๐Ÿ”ง',
150
- 'related': ['๐Ÿ”จ', 'โš’๏ธ', '๐Ÿ› ๏ธ', 'โš™๏ธ', '๐Ÿ”ฉ', 'โ›๏ธ', 'โšก', '๐Ÿ”Œ', '๐Ÿ’ก', '๐Ÿ”‹']
151
- }
152
- }
153
-
154
- # SDK์— ๋”ฐ๋ฅธ ์ด๋ชจ์ง€ ์„ ํƒ
155
- sdk_lower = sdk.lower()
156
- bg_color = get_pastel_color(index) # ์ธ๋ฑ์Šค ๊ธฐ๋ฐ˜ ์ƒ‰์ƒ ์„ ํƒ
157
- emoji_set = sdk_emoji_sets.get(sdk_lower, sdk_emoji_sets['N/A'])
158
- main_emoji = emoji_set['main']
159
-
160
- # ๋žœ๋คํ•˜๊ฒŒ 3๊ฐœ์˜ ๊ด€๋ จ ์ด๋ชจ์ง€ ์„ ํƒ
161
- decorative_emojis = random.sample(emoji_set['related'], 3)
162
-
163
- # ์ถ”๊ฐ€ ์žฅ์‹์šฉ ์ด๋ชจ์ง€
164
- general_emojis = ['๐Ÿš€', '๐Ÿ’ซ', 'โญ', '๐ŸŒŸ', 'โœจ', '๐Ÿ’ฅ', '๐Ÿ”ฅ', '๐ŸŒˆ', '๐ŸŽฏ', '๐ŸŽจ',
165
- '๐ŸŽญ', '๐ŸŽช', '๐ŸŽข', '๐ŸŽก', '๐ŸŽ ', '๐ŸŽช', '๐ŸŽญ', '๐ŸŽจ', '๐ŸŽฏ', '๐ŸŽฒ']
166
- random_emojis = random.sample(general_emojis, 3)
167
-
168
- # ์ข‹์•„์š” ์ˆ˜์— ๋”ฐ๋ฅธ ํ•˜ํŠธ ์ด๋ชจ์ง€
169
- heart_emoji = 'โค๏ธ' if likes > 100 else '๐Ÿ’–' if likes > 50 else '๐Ÿ’' if likes > 10 else '๐Ÿค'
170
-
171
-
172
-
173
-
174
- return f"""
175
- <div style='border: none;
176
- padding: 25px;
177
- margin: 15px;
178
- border-radius: 20px;
179
- background-color: {bg_color};
180
- box-shadow: 0 4px 15px rgba(0,0,0,0.1);
181
- transition: all 0.3s ease-in-out;
182
- position: relative;
183
- overflow: hidden;'
184
- onmouseover='this.style.transform="translateY(-5px) scale(1.02)"; this.style.boxShadow="0 8px 25px rgba(0,0,0,0.15)"'
185
- onmouseout='this.style.transform="translateY(0) scale(1)"; this.style.boxShadow="0 4px 15px rgba(0,0,0,0.1)"'>
186
- <div style='position: absolute; top: -15px; right: -15px; font-size: 100px; opacity: 0.1;'>
187
- {main_emoji}
188
- </div>
189
- <div style='position: absolute; top: 10px; right: 10px; font-size: 20px;'>
190
- {decorative_emojis[0]}
191
- </div>
192
- <div style='position: absolute; bottom: 10px; left: 10px; font-size: 20px;'>
193
- {decorative_emojis[1]}
194
- </div>
195
- <div style='position: absolute; top: 50%; right: 10px; font-size: 20px;'>
196
- {decorative_emojis[2]}
197
- </div>
198
- <h3 style='color: #2d2d2d;
199
- margin: 0 0 20px 0;
200
- font-size: 1.4em;
201
- display: flex;
202
- align-items: center;
203
- gap: 10px;'>
204
- <span style='font-size: 1.3em'>{random_emojis[0]}</span>
205
- <a href='https://huggingface.co/spaces/{space_id}' target='_blank'
206
- style='text-decoration: none; color: #2d2d2d;'>
207
- {space_name}
208
- </a>
209
- <span style='font-size: 1.3em'>{random_emojis[1]}</span>
210
- </h3>
211
- <div style='margin: 15px 0; color: #444; background: rgba(255,255,255,0.5);
212
- padding: 15px; border-radius: 12px;'>
213
- <p style='margin: 8px 0;'>
214
- <strong>SDK:</strong> {main_emoji} {sdk} {decorative_emojis[0]}
215
- </p>
216
- <p style='margin: 8px 0;'>
217
- <strong>Created:</strong> ๐Ÿ“… {created_at} โฐ
218
- </p>
219
- <p style='margin: 8px 0;'>
220
- <strong>Likes:</strong> {heart_emoji} {likes} {random_emojis[2]}
221
- </p>
222
- </div>
223
- <div style='margin-top: 20px;
224
- display: flex;
225
- justify-content: space-between;
226
- align-items: center;'>
227
- <a href='https://huggingface.co/spaces/{space_id}' target='_blank'
228
- style='background: linear-gradient(45deg, #0084ff, #00a3ff);
229
- color: white;
230
- padding: 10px 20px;
231
- border-radius: 15px;
232
- text-decoration: none;
233
- display: inline-flex;
234
- align-items: center;
235
- gap: 8px;
236
- font-weight: 500;
237
- transition: all 0.3s;
238
- box-shadow: 0 2px 8px rgba(0,132,255,0.3);'
239
- onmouseover='this.style.transform="scale(1.05)"; this.style.boxShadow="0 4px 12px rgba(0,132,255,0.4)"'
240
- onmouseout='this.style.transform="scale(1)"; this.style.boxShadow="0 2px 8px rgba(0,132,255,0.3)"'>
241
- <span>View Space</span> ๐Ÿš€ {random_emojis[0]}
242
- </a>
243
- <span style='color: #666; font-size: 0.9em; opacity: 0.7;'>
244
- ๐Ÿ†” {space_id} {decorative_emojis[2]}
245
- </span>
246
- </div>
247
- </div>
248
- """
249
-
250
- def get_vercel_deployments():
251
- """Vercel API๋ฅผ ํ†ตํ•ด ๋ชจ๋“  ๋ฐฐํฌ๋œ ์„œ๋น„์Šค ์ •๋ณด ๊ฐ€์ ธ์˜ค๊ธฐ (ํŽ˜์ด์ง€๋„ค์ด์…˜ ์ ์šฉ)"""
252
- token = "A8IFZmgW2cqA4yUNlLPnci0N"
253
- base_url = "https://api.vercel.com/v6/deployments"
254
- all_deployments = []
255
- has_next = True
256
- page = 1
257
- until = None # ์ฒซ ์š”์ฒญ์—์„œ๋Š” until ํŒŒ๋ผ๋ฏธํ„ฐ ์—†์Œ
258
-
259
- headers = {
260
- "Authorization": f"Bearer {token}",
261
- "Content-Type": "application/json"
262
- }
263
-
264
- try:
265
- while has_next:
266
- # URL ๊ตฌ์„ฑ (ํŽ˜์ด์ง€๋„ค์ด์…˜ ํŒŒ๋ผ๋ฏธํ„ฐ ํฌํ•จ)
267
- url = f"{base_url}?limit=100"
268
- if until:
269
- url += f"&until={until}"
270
-
271
- print(f"Fetching page {page}... URL: {url}") # ๋””๋ฒ„๊น…์šฉ
272
-
273
- response = requests.get(url, headers=headers)
274
- if response.status_code != 200:
275
- print(f"Vercel API Error: {response.text}")
276
- break
277
-
278
- data = response.json()
279
- current_deployments = data.get('deployments', [])
280
-
281
- if not current_deployments: # ๋” ์ด์ƒ ๋ฐ์ดํ„ฐ๊ฐ€ ์—†์œผ๋ฉด ์ข…๋ฃŒ
282
- break
283
-
284
- all_deployments.extend(current_deployments)
285
-
286
- # ๋‹ค์Œ ํŽ˜์ด์ง€๋ฅผ ์œ„ํ•œ until ๊ฐ’ ์„ค์ •
287
- pagination = data.get('pagination', {})
288
- until = pagination.get('next')
289
- has_next = bool(until) # until ๊ฐ’์ด ์žˆ์œผ๋ฉด ๋‹ค์Œ ํŽ˜์ด์ง€ ์กด์žฌ
290
-
291
- print(f"Page {page} fetched. Got {len(current_deployments)} deployments") # ๋””๋ฒ„๊น…์šฉ
292
- page += 1
293
-
294
- print(f"Total deployments fetched: {len(all_deployments)}") # ๋””๋ฒ„๊น…์šฉ
295
-
296
- # ์ƒํƒœ๊ฐ€ 'READY'์ด๊ณ  'url'์ด ์žˆ๋Š” ๋ฐฐํฌ๋งŒ ํ•„ํ„ฐ๋งํ•˜๊ณ  'javis1' ์ œ์™ธ
297
- active_deployments = [
298
- dep for dep in all_deployments
299
- if dep.get('state') == 'READY' and
300
- dep.get('url') and
301
- 'javis1' not in dep.get('name', '').lower()
302
- ]
303
-
304
- print(f"Active deployments after filtering: {len(active_deployments)}") # ๋””๋ฒ„๊น…์šฉ
305
- return active_deployments
306
-
307
- except Exception as e:
308
- print(f"Error fetching Vercel deployments: {str(e)}")
309
- return []
310
-
311
-
312
- def get_vercel_card(deployment, index, is_top_best=False):
313
- """Vercel ๋ฐฐํฌ ์นด๋“œ HTML ์ƒ์„ฑ ํ•จ์ˆ˜"""
314
- raw_url = deployment.get('url', '')
315
-
316
- # URL ์ฒ˜๋ฆฌ
317
- if raw_url.startswith('http'):
318
- url = raw_url
319
- else:
320
- url = f"https://{raw_url}"
321
-
322
- name = deployment.get('name', '์ด๋ฆ„ ์—†๋Š” ํ”„๋กœ์ ํŠธ')
323
-
324
- # ์นด๋“œ ID ์ƒ์„ฑ
325
- card_id = f"vercel-card-{url.replace('.', '-').replace('/', '-')}"
326
-
327
- # Top Best ํ•ญ๋ชฉ์ผ ๊ฒฝ์šฐ์˜ ์Šคํฌ๋ฆฐ์ƒท ์ฒ˜๋ฆฌ
328
- screenshot_html = ""
329
- if is_top_best:
330
- try:
331
- print(f"์Šคํฌ๋ฆฐ์ƒท ์บก์ฒ˜ ์‹œ๋„: {url}") # ๋””๋ฒ„๊น…์šฉ ๋กœ๊ทธ
332
- screenshot_base64 = take_screenshot(raw_url)
333
- if screenshot_base64:
334
- screenshot_html = f"""
335
- <div style="width: 100%; height: 200px; overflow: hidden; border-radius: 10px; margin-bottom: 15px;">
336
- <img src="data:image/png;base64,{screenshot_base64}"
337
- style="width: 100%; height: 100%; object-fit: cover;"
338
- alt="{name} ์Šคํฌ๋ฆฐ์ƒท"/>
339
- </div>
340
- """
341
- else:
342
- print(f"์Šคํฌ๋ฆฐ์ƒท ์บก์ฒ˜ ์‹คํŒจ: {url}") # ๋””๋ฒ„๊น…์šฉ ๋กœ๊ทธ
343
- except Exception as e:
344
- print(f"์Šคํฌ๋ฆฐ์ƒท ์ฒ˜๋ฆฌ ์˜ค๋ฅ˜: {str(e)} for URL: {url}") # ๋””๋ฒ„๊น…์šฉ ๋กœ๊ทธ
345
-
346
- bg_color = get_pastel_color(index + (20 if not is_top_best else 0))
347
- tech_emojis = ['โšก', '๐Ÿš€', '๐ŸŒŸ', 'โœจ', '๐Ÿ’ซ', '๐Ÿ”ฅ', '๐ŸŒˆ', '๐ŸŽฏ', '๐ŸŽจ', '๐Ÿ”ฎ']
348
- random_emojis = random.sample(tech_emojis, 3)
349
-
350
- # Top Best ์นด๋“œ์˜ ๊ฐ„์†Œํ™”๋œ ์ •๋ณด ์„น์…˜
351
- if is_top_best:
352
- info_section = f"""
353
- <div style='margin: 15px 0; color: #444; background: rgba(255,255,255,0.5);
354
- padding: 15px; border-radius: 12px;'>
355
- <p style='margin: 8px 0;'>
356
- <strong>URL:</strong> ๐Ÿ”— {url}
357
- </p>
358
- </div>
359
- """
360
- else:
361
- info_section = f"""
362
- <div style='margin: 15px 0; color: #444; background: rgba(255,255,255,0.5);
363
- padding: 15px; border-radius: 12px;'>
364
- <p style='margin: 8px 0;'>
365
- <strong>Status:</strong> โœ… {deployment.get('state', 'N/A')}
366
- </p>
367
- <p style='margin: 8px 0;'>
368
- <strong>Created:</strong> ๐Ÿ“… {format_timestamp(deployment.get('created'))}
369
- </p>
370
- <p style='margin: 8px 0;'>
371
- <strong>URL:</strong> ๐Ÿ”— {url}
372
- </p>
373
- </div>
374
- """
375
-
376
- return f"""
377
- <div id="{card_id}" class="vercel-card"
378
- data-likes="0"
379
- style='border: none;
380
- padding: 25px;
381
- margin: 15px;
382
- border-radius: 20px;
383
- background-color: {bg_color};
384
- box-shadow: 0 4px 15px rgba(0,0,0,0.1);
385
- transition: all 0.3s ease-in-out;
386
- position: relative;
387
- overflow: hidden;'
388
- onmouseover='this.style.transform="translateY(-5px) scale(1.02)"; this.style.boxShadow="0 8px 25px rgba(0,0,0,0.15)"'
389
- onmouseout='this.style.transform="translateY(0) scale(1)"; this.style.boxShadow="0 4px 15px rgba(0,0,0,0.1)"'>
390
- {screenshot_html}
391
- <h3 style='color: #2d2d2d;
392
- margin: 0 0 20px 0;
393
- font-size: 1.4em;
394
- display: flex;
395
- align-items: center;
396
- gap: 10px;'>
397
- <span style='font-size: 1.3em'>{random_emojis[0]}</span>
398
- <a href='{url}' target='_blank'
399
- style='text-decoration: none; color: #2d2d2d;'>
400
- {name}
401
- </a>
402
- <span style='font-size: 1.3em'>{random_emojis[1]}</span>
403
- </h3>
404
- {info_section}
405
- <div style='margin-top: 20px; display: flex; justify-content: space-between; align-items: center;'>
406
- <div class="like-section" style="display: flex; align-items: center; gap: 10px;">
407
- <button onclick="toggleLike('{card_id}')" class="like-button"
408
- style="background: none; border: none; cursor: pointer; font-size: 1.5em; padding: 5px 10px;">
409
- ๐Ÿค
410
- </button>
411
- <span class="like-count" style="font-size: 1.2em; color: #666;">0</span>
412
- </div>
413
- <a href='{url}' target='_blank'
414
- style='background: linear-gradient(45deg, #0084ff, #00a3ff);
415
- color: white;
416
- padding: 10px 20px;
417
- border-radius: 15px;
418
- text-decoration: none;
419
- display: inline-flex;
420
- align-items: center;
421
- gap: 8px;
422
- font-weight: 500;
423
- transition: all 0.3s;
424
- box-shadow: 0 2px 8px rgba(0,132,255,0.3);'
425
- onmouseover='this.style.transform="scale(1.05)"; this.style.boxShadow="0 4px 12px rgba(0,132,255,0.4)"'
426
- onmouseout='this.style.transform="scale(1)"; this.style.boxShadow="0 2px 8px rgba(0,132,255,0.3)"'>
427
- <span>View Deployment</span> ๐Ÿš€ {random_emojis[0]}
428
- </a>
429
- </div>
430
- </div>
431
- """
432
-
433
- # Top Best URLs ์ •์˜
434
- TOP_BEST_URLS = [
435
-
436
- {
437
- "url": "dekvxz.vercel.app",
438
- "name": "[๊ฒŒ์ž„] ๋‹ค์ด์–ดํŠธ ํ—Œํ„ฐ",
439
- "created": "2024-11-20 00:00",
440
- "state": "READY"
441
- },
442
- {
443
- "url": "jtufui.vercel.app",
444
- "name": "[๊ฒŒ์ž„] ํ…Œ๋Ÿฌ๋ฆฌ์ŠคํŠธ",
445
- "created": "2024-11-20 00:00",
446
- "state": "READY"
447
- },
448
- {
449
- "url": "https://huggingface.co/spaces/openfree/ggumim",
450
- "name": "[MOUSE-II] ์ด๋ฏธ์ง€์— ํ•œ๊ธ€ ์ถœ๋ ฅ",
451
- "created": "2024-11-18 00:00",
452
- "state": "READY"
453
- },
454
- {
455
- "url": "xabtnc.vercel.app",
456
- "name": "[ChatGPT] ๋‚˜๋งŒ์˜ LLM",
457
- "created": "2024-11-18 00:00",
458
- "state": "READY"
459
- },
460
- {
461
- "url": "https://huggingface.co/spaces/openfree/ifbhdc",
462
- "name": "[๊ฒŒ์ž„] ๋ณด์„ ํŒกํŒก",
463
- "created": "2024-11-18 00:00",
464
- "state": "READY"
465
- },
466
- {
467
- "url": "nxhquk.vercel.app",
468
- "name": "[๊ฒŒ์ž„] ํ…ŒํŠธ๋ฆฌ์Šค",
469
- "created": "2024-11-18 00:00",
470
- "state": "READY"
471
- },
472
- {
473
- "url": "bydcnd.vercel.app",
474
- "name": "[๋ชจ๋ธ] 3D ๋ถ„์ž ๋ชจํ˜•",
475
- "created": "2024-11-18 00:00",
476
- "state": "READY"
477
- },
478
- {
479
- "url": "ijhama.vercel.app",
480
- "name": "ํˆฌ์ž ํฌํŠธํด๋ฆฌ์˜ค ๋ถ„์„",
481
- "created": "2024-11-18 00:00",
482
- "state": "READY"
483
- },
484
- {
485
- "url": "oschnl.vercel.app",
486
- "name": "๋กœ๋˜ ๋ฒˆํ˜ธ ๋ถ„์„/์ถ”์ฒœ",
487
- "created": "2024-11-18 00:00",
488
- "state": "READY"
489
- },
490
- {
491
- "url": "rzwzrq.vercel.app",
492
- "name": "์—‘์…€/CSV ๋ฐ์ดํ„ฐ ๋ถ„์„",
493
- "created": "2024-11-18 00:00",
494
- "state": "READY"
495
- },
496
- {
497
- "url": "twkqre.vercel.app",
498
- "name": "[์šด์„ธ] ํƒ€๋กœ์นด๋“œ",
499
- "created": "2024-11-18 00:00",
500
- "state": "READY"
501
- },
502
- {
503
- "url": "htwymz.vercel.app",
504
- "name": "[๊ฒŒ์ž„] ์†Œ๋ฐฉํ—ฌ๊ธฐ",
505
- "created": "2024-11-20 00:00",
506
- "state": "READY"
507
- },
508
- {
509
- "url": "mktmbn.vercel.app",
510
- "name": "[๊ฒŒ์ž„] ์šฐ์ฃผ์ „์Ÿ",
511
- "created": "2024-11-19 00:00",
512
- "state": "READY"
513
- },
514
- {
515
- "url": "euguwt.vercel.app",
516
- "name": "[๊ฒŒ์ž„] ํฌ์„ธ์ด๋ˆ",
517
- "created": "2024-11-19 00:00",
518
- "state": "READY"
519
- },
520
- {
521
- "url": "qmdzoh.vercel.app",
522
- "name": "[๊ฒŒ์ž„] ํ•˜๋Š˜์„ ์ง€์ผœ๋ผ",
523
- "created": "2024-11-19 00:00",
524
- "state": "READY"
525
- },
526
- {
527
- "url": "kofaqo.vercel.app",
528
- "name": "[๊ฒŒ์ž„] ์šด์„ ์ถฉ๋Œ!",
529
- "created": "2024-11-19 00:00",
530
- "state": "READY"
531
- },
532
- {
533
- "url": "qoqqkq.vercel.app",
534
- "name": "[๊ฒŒ์ž„] ๋‘๋”์ฅ ์žก๊ธฐ",
535
- "created": "2024-11-19 00:00",
536
- "state": "READY"
537
- },
538
- {
539
- "url": "nmznel.vercel.app",
540
- "name": "[๊ฒŒ์ž„] ๊ณ ์–‘์ด ์ „์šฉ",
541
- "created": "2024-11-19 00:00",
542
- "state": "READY"
543
- },
544
-
545
-
546
- {
547
- "url": "psrrtp.vercel.app",
548
- "name": "[๋Œ€์‹œ๋ณด๋“œ] ์„ธ๊ณ„ ์ธ๊ตฌ",
549
- "created": "2024-11-18 00:00",
550
- "state": "READY"
551
- },
552
- {
553
- "url": "xxloav.vercel.app",
554
- "name": "[๊ฒŒ์ž„] ๋ฒฝ๋Œ ๊นจ๊ธฐ",
555
- "created": "2024-11-18 00:00",
556
- "state": "READY"
557
- },
558
- {
559
- "url": "https://huggingface.co/spaces/openfree/edpaje",
560
- "name": "[๊ฒŒ์ž„] ๊ธฐ์–ต๋ ฅ ์นด๋“œ",
561
- "created": "2024-11-18 00:00",
562
- "state": "READY"
563
- },
564
- {
565
- "url": "https://huggingface.co/spaces/openfree/ixtidb",
566
- "name": "AI ์š”๋ฆฌ์‚ฌ",
567
- "created": "2024-11-18 00:00",
568
- "state": "READY"
569
- },
570
-
571
- {
572
- "url": "cnlzji.vercel.app",
573
- "name": "๊ตญ๊ฐ€ ์ •๋ณด ๋น„๊ต",
574
- "created": "2024-11-18 00:00",
575
- "state": "READY"
576
- },
577
- {
578
- "url": "fazely.vercel.app",
579
- "name": "Wikipedia ์ง€์‹ ๋ถ„์„",
580
- "created": "2024-11-18 00:00",
581
- "state": "READY"
582
- },
583
- {
584
- "url": "pkzhbo.vercel.app",
585
- "name": "์„ธ๊ณ„ ๊ตญ๊ฐ€๋ณ„ ์‹œ๊ฐ„๋Œ€",
586
- "created": "2024-11-18 00:00",
587
- "state": "READY"
588
- },
589
- {
590
- "url": "pammgl.vercel.app",
591
- "name": "๋ณด๋„์ž๋ฃŒ ๋ฐฐํฌ ์„œ๋น„์Šค",
592
- "created": "2024-11-18 00:00",
593
- "state": "READY"
594
- },
595
-
596
-
597
- {
598
- "url": "https://ktduhm.vercel.app/",
599
- "name": "์ˆ˜ํ•™์„ ๊ทธ๋ž˜ํ”„๋กœ ์ดํ•ด",
600
- "created": "2024-11-18 00:00",
601
- "state": "READY"
602
- },
603
-
604
-
605
- {
606
- "url": "vjmfoy.vercel.app",
607
- "name": "[๊ฒŒ์ž„] 3D ๋ฒฝ๋Œ์Œ“๊ธฐ",
608
- "created": "2024-11-18 00:00",
609
- "state": "READY"
610
- },
611
- {
612
- "url": "aodakf.vercel.app",
613
- "name": "[๋ฒ„์ถ”์–ผ] 3D ๊ฐ€์ƒํ˜„์‹ค",
614
- "created": "2024-11-18 00:00",
615
- "state": "READY"
616
- },
617
- {
618
- "url": "mxoeue.vercel.app",
619
- "name": "์Œ์„ฑ ์ƒ์„ฑ(TTS),์กฐ์ •",
620
- "created": "2024-11-18 00:00",
621
- "state": "READY"
622
- }
623
- ]
624
-
625
-
626
- def get_user_spaces():
627
- # ๊ธฐ์กด Hugging Face ์ŠคํŽ˜์ด์Šค ๊ฐ€์ ธ์˜ค๊ธฐ
628
- url = f"https://huggingface.co/api/spaces?author={USERNAME}&limit=500"
629
- headers = {
630
- "Accept": "application/json",
631
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
632
- }
633
-
634
- try:
635
- # Hugging Face ์ŠคํŽ˜์ด์Šค ๊ฐ€์ ธ์˜ค๊ธฐ
636
- response = requests.get(url, headers=headers)
637
- spaces_data = response.json() if response.status_code == 200 else []
638
-
639
- # ์ œ์™ธํ•  ์ŠคํŽ˜์ด์Šค ํ•„ํ„ฐ๋ง
640
- user_spaces = [
641
- space for space in spaces_data
642
- if not should_exclude_space(space.get('id', '').split('/')[-1])
643
- ]
644
-
645
- # TOP_BEST_URLS ํ•ญ๋ชฉ ์ˆ˜
646
- top_best_count = len(TOP_BEST_URLS)
647
-
648
- # Vercel API๋ฅผ ํ†ตํ•œ ์‹ค์ œ ๋ฐฐํฌ ์ˆ˜
649
- vercel_deployments = get_vercel_deployments()
650
- actual_vercel_count = len(vercel_deployments) if vercel_deployments else 0
651
-
652
-
653
- html_content = f"""
654
- <div style='
655
- min-height: 100vh;
656
- background: linear-gradient(135deg, #f6f8ff 0%, #f0f4ff 100%);
657
- background-image: url("data:image/svg+xml,%3Csvg width='100' height='20' viewBox='0 0 100 20' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M21.184 20c.357-.13.72-.264 1.088-.402l1.768-.661C33.64 15.347 39.647 14 50 14c10.271 0 15.362 1.222 24.629 4.928.955.383 1.869.74 2.75 1.072h6.225c-2.51-.73-5.139-1.691-8.233-2.928C65.888 13.278 60.562 12 50 12c-10.626 0-16.855 1.397-26.66 5.063l-1.767.662c-2.475.923-4.66 1.674-6.724 2.275h6.335zm0-20C13.258 2.892 8.077 4 0 4V2c5.744 0 9.951-.574 14.85-2h6.334zM77.38 0C85.239 2.966 90.502 4 100 4V2c-6.842 0-11.386-.542-16.396-2h-6.225zM0 14c8.44 0 13.718-1.21 22.272-4.402l1.768-.661C33.64 5.347 39.647 4 50 4c10.271 0 15.362 1.222 24.629 4.928C84.112 12.722 89.438 14 100 14v-2c-10.271 0-15.362-1.222-24.629-4.928C65.888 3.278 60.562 2 50 2 39.374 2 33.145 3.397 23.34 7.063l-1.767.662C13.223 10.84 8.163 12 0 12v2z' fill='%23f0f0f0' fill-opacity='0.2' fill-rule='evenodd'/%3E%3C/svg%3E");
658
- padding: 40px;
659
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;'>
660
-
661
- <!-- ๋ฉ”์ธ ํ—ค๋” -->
662
- <div style='
663
- background: rgba(255, 255, 255, 0.8);
664
- border-radius: 20px;
665
- padding: 30px;
666
- margin-bottom: 40px;
667
- box-shadow: 0 4px 20px rgba(0,0,0,0.05);
668
- backdrop-filter: blur(10px);
669
- border: 1px solid rgba(255,255,255,0.8);'>
670
-
671
- <h2 style='
672
- color: #2d2d2d;
673
- margin: 0 0 15px 0;
674
- font-size: 2em;
675
- background: linear-gradient(45deg, #2d2d2d, #0084ff);
676
- -webkit-background-clip: text;
677
- -webkit-text-fill-color: transparent;'>
678
- ๊ณต๊ฐœ ๊ฐค๋Ÿฌ๋ฆฌ(์ƒ์„ฑ Web/App) by MOUSE
679
- </h2>
680
-
681
- <div style='
682
- background: linear-gradient(45deg, #0084ff, #00a3ff);
683
- border-radius: 10px;
684
- padding: 15px;
685
- margin: 20px 0;'>
686
- <a href='https://openfree-mouse.hf.space'
687
- target='_blank'
688
- style='
689
- color: white;
690
- text-decoration: none;
691
- font-size: 1.1em;
692
- display: block;
693
- text-align: center;'>
694
- ๐Ÿš€ ํ”„๋กฌํ”„ํŠธ๋งŒ์œผ๋กœ ๋‚˜๋งŒ์˜ ์›น์„œ๋น„์Šค๋ฅผ ์ฆ‰์‹œ ์ƒ์„ฑํ•˜๋Š” MOUSE
695
- </a>
696
- </div>
697
-
698
- <p style='
699
- color: #666;
700
- margin: 0;
701
- font-size: 0.9em;
702
- text-align: center;
703
- background: rgba(255,255,255,0.5);
704
- padding: 10px;
705
- border-radius: 10px;'>
706
- Found {actual_vercel_count} Vercel deployments and {len(user_spaces)} Hugging Face spaces<br>
707
- (Plus {top_best_count} featured items in Top Best section)
708
- </p>
709
- </div>
710
-
711
- <!-- Top Best ์„น์…˜ -->
712
- <div class="section-container" style='
713
- background: rgba(255, 255, 255, 0.4);
714
- border-radius: 20px;
715
- padding: 30px;
716
- margin: 20px 0;
717
- backdrop-filter: blur(10px);'>
718
-
719
- <h3 style='
720
- color: #2d2d2d;
721
- margin: 0 0 20px 0;
722
- padding: 15px 25px;
723
- background: rgba(255,255,255,0.7);
724
- border-radius: 15px;
725
- box-shadow: 0 4px 15px rgba(0,0,0,0.05);
726
- border-left: 5px solid #0084ff;
727
- display: flex;
728
- align-items: center;
729
- gap: 10px;'>
730
- <span style='font-size: 1.5em;'>๐Ÿ†</span>
731
- Top Best
732
- </h3>
733
-
734
- <div style='
735
- display: grid;
736
- grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
737
- gap: 20px;'>
738
- {"".join(get_vercel_card(
739
- {"url": url["url"], "created": url["created"], "name": url["name"], "state": url["state"]},
740
- idx,
741
- is_top_best=True
742
- ) for idx, url in enumerate(TOP_BEST_URLS))}
743
- </div>
744
- </div>
745
-
746
- <!-- Vercel Deployments ์„น์…˜ -->
747
- {f'''
748
- <div class="section-container" style='
749
- background: rgba(255, 255, 255, 0.4);
750
- border-radius: 20px;
751
- padding: 30px;
752
- margin: 20px 0;
753
- backdrop-filter: blur(10px);'>
754
-
755
- <h3 style='
756
- color: #2d2d2d;
757
- margin: 0 0 20px 0;
758
- padding: 15px 25px;
759
- background: rgba(255,255,255,0.7);
760
- border-radius: 15px;
761
- box-shadow: 0 4px 15px rgba(0,0,0,0.05);
762
- border-left: 5px solid #00a3ff;
763
- display: flex;
764
- align-items: center;
765
- gap: 10px;'>
766
- <span style='font-size: 1.5em;'>โšก</span>
767
- Vercel Deployments
768
- </h3>
769
-
770
- <div id="vercel-container" style='
771
- display: grid;
772
- grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
773
- gap: 20px;'>
774
- {"".join(get_vercel_card(dep, idx) for idx, dep in enumerate(vercel_deployments))}
775
- </div>
776
- </div>
777
- ''' if vercel_deployments else ''}
778
-
779
- <!-- Hugging Face Spaces ์„น์…˜ -->
780
- <div class="section-container" style='
781
- background: rgba(255, 255, 255, 0.4);
782
- border-radius: 20px;
783
- padding: 30px;
784
- margin: 20px 0;
785
- backdrop-filter: blur(10px);'>
786
-
787
- <h3 style='
788
- color: #2d2d2d;
789
- margin: 0 0 20px 0;
790
- padding: 15px 25px;
791
- background: rgba(255,255,255,0.7);
792
- border-radius: 15px;
793
- box-shadow: 0 4px 15px rgba(0,0,0,0.05);
794
- border-left: 5px solid #ff6b6b;
795
- display: flex;
796
- align-items: center;
797
- gap: 10px;'>
798
- <span style='font-size: 1.5em;'>๐Ÿค—</span>
799
- Hugging Face Spaces
800
- </h3>
801
-
802
- <div style='
803
- display: grid;
804
- grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
805
- gap: 20px;'>
806
- {"".join(get_space_card(space, idx) for idx, space in enumerate(user_spaces))}
807
- </div>
808
- </div>
809
- </div>
810
-
811
- <!-- ๊ธฐ์กด JavaScript ์ฝ”๋“œ๋Š” ๊ทธ๋Œ€๋กœ ์œ ์ง€ -->
812
- <script>
813
- // ... (๊ธฐ์กด JavaScript ์ฝ”๋“œ)
814
- </script>
815
- """
816
-
817
- return html_content
818
-
819
- except Exception as e:
820
- print(f"Error: {str(e)}")
821
- return f"""
822
- <div style='padding: 20px; text-align: center; color: #666;'>
823
- <h2>Error occurred while fetching spaces</h2>
824
- <p>Error details: {str(e)}</p>
825
- <p>Please try again later.</p>
826
- </div>
827
- """
828
-
829
-
830
- # Creating the Gradio interface
831
- demo = gr.Blocks()
832
-
833
- with demo:
834
- html_output = gr.HTML(value=get_user_spaces())
835
-
836
- if __name__ == "__main__":
837
- demo.launch()
838
-