openfree commited on
Commit
14367c0
ยท
verified ยท
1 Parent(s): f62846d

Delete app-backup-last.py

Browse files
Files changed (1) hide show
  1. app-backup-last.py +0 -177
app-backup-last.py DELETED
@@ -1,177 +0,0 @@
1
- import os, json, time, datetime, requests, gradio as gr
2
-
3
- # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ 1. ๊ธฐ๋ณธ ์„ค์ • โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
4
- BEST_FILE, PER_PAGE = "best_games.json", 9 # โถ ํŽ˜์ด์ง€๋‹น 9๊ฐœ ์œ ์ง€
5
-
6
- # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ 2. BEST ๋ฐ์ดํ„ฐ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
7
- def _init_best():
8
- if not os.path.exists(BEST_FILE):
9
- json.dump([], open(BEST_FILE, "w"), ensure_ascii=False)
10
-
11
- def _load_best():
12
- try:
13
- raw = json.load(open(BEST_FILE))
14
- # URL ๋ฆฌ์ŠคํŠธ๋งŒ ๋ฐ˜ํ™˜
15
- if isinstance(raw, list):
16
- return [u if isinstance(u, str) else u.get("url") for u in raw]
17
- return []
18
- except Exception as e:
19
- print("BEST ๋กœ๋“œ ์˜ค๋ฅ˜:", e)
20
- return []
21
-
22
- def _save_best(lst): # URLโ€†๋ฆฌ์ŠคํŠธ ์ €์žฅ
23
- try:
24
- json.dump(lst, open(BEST_FILE, "w"), ensure_ascii=False, indent=2)
25
- return True
26
- except Exception as e:
27
- print("BEST ์ €์žฅ ์˜ค๋ฅ˜:", e)
28
- return False
29
-
30
- def add_url_to_best(url: str):
31
- data = _load_best()
32
- if url in data:
33
- return False
34
- data.insert(0, url)
35
- return _save_best(data)
36
-
37
- # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ 3. ์œ ํ‹ธ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
38
- def page(lst, pg):
39
- s, e = (pg-1)*PER_PAGE, (pg-1)*PER_PAGE+PER_PAGE
40
- total = (len(lst)+PER_PAGE-1)//PER_PAGE
41
- return lst[s:e], total
42
-
43
- def process_url_for_iframe(url):
44
- # Hugging Face Spaces embed ์šฐ์„ 
45
- if "huggingface.co/spaces" in url:
46
- owner, name = url.rstrip("/").split("/spaces/")[1].split("/")[:2]
47
- return f"https://huggingface.co/spaces/{owner}/{name}/embed", True, []
48
- return url, False, []
49
-
50
- # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ 6. HTML ๊ทธ๋ฆฌ๋“œ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
51
- def html(cards, pg, total):
52
- if not cards:
53
- return "<div style='text-align:center;padding:70px;color:#555;'>ํ‘œ์‹œํ•  ๋ฐฐํฌ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.</div>"
54
-
55
- css = r"""
56
- <style>
57
- /* ํŒŒ์Šคํ…” ๊ทธ๋ผ๋””์—์ด์…˜ ๋ฐฐ๊ฒฝ */
58
- body{
59
- margin:0;padding:0;font-family:Poppins,sans-serif;
60
- background:linear-gradient(135deg,#fdf4ff 0%,#f6fbff 50%,#fffaf4 100%);
61
- background-attachment:fixed;
62
- overflow-x:hidden;overflow-y:auto;
63
- }
64
-
65
- .container{width:100%;padding:10px 10px 70px;box-sizing:border-box;}
66
- .grid{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;width:100%;}
67
- .card{
68
- background:#fff;border-radius:10px;overflow:hidden;box-shadow:0 4px 10px rgba(0,0,0,0.08);
69
- height:420px;display:flex;flex-direction:column;position:relative;
70
- }
71
-
72
- /* ๊ฒŒ์ž„ ํ™”๋ฉด ์ถ•์†Œ */
73
- .frame{flex:1;position:relative;overflow:hidden;}
74
- .frame iframe{
75
- position:absolute;top:0;left:0;
76
- width:166.667%;height:166.667%;
77
- transform:scale(0.6);transform-origin:top left;border:0;
78
- }
79
- .frame.huggingface iframe{width:100%!important;height:100%!important;transform:none!important;border:none!important;}
80
-
81
- /* ํ•˜๋‹จ ๋ฐ”๋กœ๊ฐ€๊ธฐ */
82
- .foot{height:34px;display:flex;align-items:center;justify-content:center;background:#fafafa;border-top:1px solid #eee;}
83
- .foot a{font-size:0.85rem;font-weight:600;color:#4a6dd8;text-decoration:none;}
84
- .foot a:hover{text-decoration:underline;}
85
-
86
- /* ๋ฐ˜์‘ํ˜• ๋†’์ด */
87
- @media(min-width:1200px){.card{height:560px;}}
88
- @media(max-width:767px){
89
- .grid{grid-template-columns:1fr;}
90
- .card{height:480px;}
91
- }
92
- </style>"""
93
-
94
- js = """
95
- <script>
96
- /* ํ—ˆ๊น…ํŽ˜์ด์Šค iframe ๋กœ๋”ฉ ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ(์ƒ๋žต - ๊ธฐ์กด ์Šคํฌ๋ฆฝํŠธ ๊ทธ๋Œ€๋กœ) */
97
- </script>
98
- """
99
-
100
- h = css + js + '<div class="container"><div class="grid">'
101
- for idx, url in enumerate(cards):
102
- iframe_url, is_huggingface, alt_urls = process_url_for_iframe(url)
103
- frame_class = "frame huggingface" if is_huggingface else "frame"
104
- iframe_id = f"iframe-{idx}-{hash(url)%10000}"
105
- alt_attr = f'data-alternate-urls="{",".join(alt_urls)}"' if alt_urls else ""
106
- h += f"""
107
- <div class="card">
108
- <div class="{frame_class}">
109
- <iframe id="{iframe_id}" src="{iframe_url}" loading="lazy"
110
- sandbox="allow-forms allow-modals allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts allow-downloads"
111
- data-original-url="{url}" {alt_attr}></iframe>
112
- </div>
113
- <div class="foot"><a href="{url}" target="_blank">โ†— ํฐ ํ™”๋ฉด(์ƒˆ ํƒญ)์œผ๋กœ ์—ด๊ธฐ</a></div>
114
- </div>"""
115
- h += "</div></div>"
116
- h += f'<div class="page-info">Page {pg} / {total}</div>'
117
- return h
118
-
119
-
120
- # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ 5. Gradio UI โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
121
- def build():
122
- _init_best()
123
-
124
- header = """
125
- <style>
126
- .app-header{position:sticky;top:0;text-align:center;background:#fff;
127
- padding:16px 0 8px;border-bottom:1px solid #eee;z-index:1100;}
128
- .badge-row{display:inline-flex;gap:8px;margin:8px 0;}
129
- </style>
130
- <div class="app-header">
131
- <h1 style="margin:0;font-size:28px;">๐ŸŽฎ Vibe Game Gallery</h1>
132
- <div class="badge-row">
133
- <a href="https://huggingface.co/spaces/openfree/Vibe-Game" target="_blank">
134
- <img src="https://img.shields.io/static/v1?label=huggingface&message=Vibe%20Game%20Craft&color=800080&labelColor=ffa500&logo=huggingface&logoColor=ffff00&style=for-the-badge">
135
- </a>
136
- <a href="https://huggingface.co/spaces/openfree/Game-Gallery" target="_blank">
137
- <img src="https://img.shields.io/static/v1?label=huggingface&message=Game%20Gallery&color=800080&labelColor=ffa500&logo=huggingface&logoColor=ffff00&style=for-the-badge">
138
- </a>
139
- <a href="https://discord.gg/openfreeai" target="_blank">
140
- <img src="https://img.shields.io/static/v1?label=Discord&message=Openfree%20AI&color=0000ff&labelColor=800080&logo=discord&logoColor=white&style=for-the-badge">
141
- </a>
142
- </div>
143
- </div>"""
144
-
145
- global_css = """
146
- footer{display:none !important;}
147
- .button-row{position:fixed;bottom:0;left:0;right:0;height:60px;
148
- background:#f0f0f0;padding:10px;text-align:center;
149
- box-shadow:0 -2px 10px rgba(0,0,0,.05);z-index:1000;}
150
- .button-row button{margin:0 10px;padding:10px 20px;font-size:16px;font-weight:bold;border-radius:50px;}
151
- #content-area{overflow-y:auto;height:calc(100vh - 60px - 120px);}
152
- """
153
-
154
- with gr.Blocks(title="Vibe Game Gallery", css=global_css) as demo:
155
- gr.HTML(header)
156
- out = gr.HTML(elem_id="content-area")
157
- with gr.Row(elem_classes="button-row"):
158
- b_prev = gr.Button("โ—€ ์ด์ „", size="lg")
159
- b_next = gr.Button("๋‹ค์Œ โ–ถ", size="lg")
160
-
161
- bp = gr.State(1)
162
-
163
- def render(p=1):
164
- data, tot = page(_load_best(), p)
165
- return html(data, p, tot), p
166
-
167
- b_prev.click(lambda p: render(max(1, p-1)), inputs=bp, outputs=[out, bp])
168
- b_next.click(lambda p: render(p+1), inputs=bp, outputs=[out, bp])
169
-
170
- demo.load(render, outputs=[out, bp])
171
-
172
- return demo
173
-
174
- app = build()
175
-
176
- if __name__ == "__main__":
177
- app.launch()