soiz1 commited on
Commit
48be6fe
·
verified ·
1 Parent(s): 334dd32

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +230 -8
app.py CHANGED
@@ -1,14 +1,34 @@
1
  import json
2
  import requests
3
- from flask import Flask, render_template, request, jsonify
 
4
 
5
  app = Flask(__name__)
6
- #
 
 
 
7
 
8
  @app.route("/", methods=["GET", "POST"])
9
  def index():
10
  if request.method == "POST":
11
- token = request.form["token"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  space_name = request.form["space_name"]
13
  github_url = request.form["github_url"]
14
  github_token = request.form.get("github_token")
@@ -21,11 +41,9 @@ def index():
21
  emoji = request.form["emoji"]
22
  pinned = request.form.get("pinned") == "on"
23
 
24
- # GitHubのIDだけの入力にも対応
25
  if not github_url.startswith("https://"):
26
  github_url = f"https://github.com/{github_url}"
27
 
28
- # Hugging Face ユーザー名を取得(または入力フォームから取得してもOK)
29
  headers = {"Authorization": f"Bearer {token}"}
30
  user_info = requests.get("https://huggingface.co/api/whoami-v2", headers=headers).json()
31
  username = user_info["name"]
@@ -63,7 +81,211 @@ def index():
63
  except requests.exceptions.JSONDecodeError:
64
  return f"エラー内容(JSON形式でない可能性): {response.text}", response.status_code
65
 
66
- return render_template("index.html")
67
- if __name__ == "__main__":
68
- app.run(host="0.0.0.0", port=7860)
69
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import json
2
  import requests
3
+ from flask import Flask, render_template_string, request, jsonify, redirect, url_for
4
+ import secrets
5
 
6
  app = Flask(__name__)
7
+ app.secret_key = secrets.token_hex(16)
8
+
9
+ # 簡易的なOAuth状態管理
10
+ oauth_state = {}
11
 
12
  @app.route("/", methods=["GET", "POST"])
13
  def index():
14
  if request.method == "POST":
15
+ # OAuthコールバック処理
16
+ if "code" in request.args and "state" in request.args:
17
+ state = request.args["state"]
18
+ if state not in oauth_state:
19
+ return "無効な状態トークン", 400
20
+
21
+ code = request.args["code"]
22
+ # 実際にはここでHugging FaceのOAuthトークンエンドポイントにリクエストを送信
23
+ # デモ用に簡略化
24
+ token = f"oauth-token-{code}" # 実際には取得したトークンを使用
25
+ return render_index(token=token)
26
+
27
+ # スペース作成処理
28
+ token = request.form.get("token")
29
+ if not token:
30
+ return "トークンが提供されていません", 400
31
+
32
  space_name = request.form["space_name"]
33
  github_url = request.form["github_url"]
34
  github_token = request.form.get("github_token")
 
41
  emoji = request.form["emoji"]
42
  pinned = request.form.get("pinned") == "on"
43
 
 
44
  if not github_url.startswith("https://"):
45
  github_url = f"https://github.com/{github_url}"
46
 
 
47
  headers = {"Authorization": f"Bearer {token}"}
48
  user_info = requests.get("https://huggingface.co/api/whoami-v2", headers=headers).json()
49
  username = user_info["name"]
 
81
  except requests.exceptions.JSONDecodeError:
82
  return f"エラー内容(JSON形式でない可能性): {response.text}", response.status_code
83
 
84
+ return render_index()
 
 
85
 
86
+ def render_index(token=None):
87
+ return render_template_string('''
88
+ <!DOCTYPE html>
89
+ <html lang="ja">
90
+ <head>
91
+ <meta charset="UTF-8" />
92
+ <title>HuggingFace Space 作成フォーム</title>
93
+ <style>
94
+ .tab {
95
+ overflow: hidden;
96
+ border: 1px solid #ccc;
97
+ background-color: #f1f1f1;
98
+ border-radius: 4px 4px 0 0;
99
+ }
100
+ .tab button {
101
+ background-color: inherit;
102
+ float: left;
103
+ border: none;
104
+ outline: none;
105
+ cursor: pointer;
106
+ padding: 10px 16px;
107
+ transition: 0.3s;
108
+ }
109
+ .tab button:hover {
110
+ background-color: #ddd;
111
+ }
112
+ .tab button.active {
113
+ background-color: #fff;
114
+ border-bottom: 2px solid #4CAF50;
115
+ }
116
+ .tabcontent {
117
+ display: none;
118
+ padding: 20px;
119
+ border: 1px solid #ccc;
120
+ border-top: none;
121
+ border-radius: 0 0 4px 4px;
122
+ }
123
+ .tabcontent.active {
124
+ display: block;
125
+ }
126
+ .form-group {
127
+ margin-bottom: 15px;
128
+ }
129
+ label {
130
+ display: block;
131
+ margin-bottom: 5px;
132
+ font-weight: bold;
133
+ }
134
+ input, select {
135
+ width: 100%;
136
+ padding: 8px;
137
+ box-sizing: border-box;
138
+ border: 1px solid #ddd;
139
+ border-radius: 4px;
140
+ }
141
+ button[type="submit"] {
142
+ background-color: #4CAF50;
143
+ color: white;
144
+ padding: 10px 15px;
145
+ border: none;
146
+ border-radius: 4px;
147
+ cursor: pointer;
148
+ }
149
+ button[type="submit"]:hover {
150
+ background-color: #45a049;
151
+ }
152
+ </style>
153
+ </head>
154
+ <body>
155
+ <h1>Hugging Face Space 作成</h1>
156
+
157
+ <div class="tab">
158
+ <button class="tablinks active" onclick="openTab(event, 'tokenTab')">トークン入力</button>
159
+ <button class="tablinks" onclick="openTab(event, 'oauthTab')">Hugging Faceでログイン</button>
160
+ </div>
161
+
162
+ <form method="POST">
163
+ <div id="tokenTab" class="tabcontent active">
164
+ <div class="form-group">
165
+ <label for="token">Hugging Face 書き込みトークン:</label>
166
+ <input type="password" name="token" id="token" required>
167
+ </div>
168
+ </div>
169
+
170
+ <div id="oauthTab" class="tabcontent">
171
+ <div class="form-group">
172
+ <p>Hugging FaceのOAuthを使用してログインします。</p>
173
+ <button type="button" id="oauthLogin" onclick="startOAuth()">Hugging Faceでログイン</button>
174
+ </div>
175
+ </div>
176
+
177
+ <div class="form-group">
178
+ <label for="space_name">スペース名:</label>
179
+ <input type="text" name="space_name" id="space_name" required>
180
+ </div>
181
+
182
+ <div class="form-group">
183
+ <label for="github_url">GitHub リポジトリURL または ID:</label>
184
+ <input type="text" name="github_url" id="github_url" required>
185
+ </div>
186
+
187
+ <div class="form-group">
188
+ <label for="github_token">GitHub トークン (必要な場合):</label>
189
+ <input type="password" name="github_token" id="github_token">
190
+ </div>
191
+
192
+ <div class="form-group">
193
+ <label>
194
+ <input type="checkbox" name="private" id="private">
195
+ 非公開にする
196
+ </label>
197
+ </div>
198
+
199
+ <div class="form-group">
200
+ <label for="sdk">SDK:</label>
201
+ <select name="sdk" id="sdk">
202
+ <option value="gradio">Gradio</option>
203
+ <option value="streamlit">Streamlit</option>
204
+ <option value="static">Static</option>
205
+ <option value="docker">Docker</option>
206
+ </select>
207
+ </div>
208
+
209
+ <div class="form-group">
210
+ <label for="description">説明:</label>
211
+ <input type="text" name="description" id="description">
212
+ </div>
213
+
214
+ <div class="form-group">
215
+ <label for="license">ライセンス:</label>
216
+ <input type="text" name="license" id="license" placeholder="e.g. apache-2.0">
217
+ </div>
218
+
219
+ <div class="form-group">
220
+ <label for="port">アプリのポート:</label>
221
+ <input type="text" name="port" id="port" placeholder="例: 7860">
222
+ </div>
223
+
224
+ <div class="form-group">
225
+ <label for="title">スペースの名前 (表示用):</label>
226
+ <input type="text" name="title" id="title">
227
+ </div>
228
+
229
+ <div class="form-group">
230
+ <label for="emoji">絵文字 (表示アイコン):</label>
231
+ <input type="text" name="emoji" id="emoji" placeholder="例: 🚀">
232
+ </div>
233
+
234
+ <div class="form-group">
235
+ <label>
236
+ <input type="checkbox" name="pinned" id="pinned">
237
+ 固定 (ピン止め)
238
+ </label>
239
+ </div>
240
+
241
+ <button type="submit">スペースを作成</button>
242
+ </form>
243
+
244
+ <script>
245
+ function openTab(evt, tabName) {
246
+ const tabcontent = document.getElementsByClassName("tabcontent");
247
+ for (let i = 0; i < tabcontent.length; i++) {
248
+ tabcontent[i].classList.remove("active");
249
+ }
250
+
251
+ const tablinks = document.getElementsByClassName("tablinks");
252
+ for (let i = 0; i < tablinks.length; i++) {
253
+ tablinks[i].classList.remove("active");
254
+ }
255
+
256
+ document.getElementById(tabName).classList.add("active");
257
+ evt.currentTarget.classList.add("active");
258
+ }
259
+
260
+ function startOAuth() {
261
+ // 実際のアプリではHugging FaceのOAuthエンドポイントを使用
262
+ // デモ用に簡略化
263
+ const state = Math.random().toString(36).substring(2);
264
+ window.location.href = `https://huggingface.co/oauth/authorize?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=${encodeURIComponent(window.location.origin)}&scope=read-repos,write-repos&state=${state}`;
265
+ }
266
+
267
+ document.addEventListener("DOMContentLoaded", () => {
268
+ const tokenInput = document.getElementById("token");
269
+
270
+ // URLからOAuthトークンを取得 (デモ用)
271
+ const urlParams = new URLSearchParams(window.location.search);
272
+ const oauthToken = urlParams.get('oauth_token');
273
+
274
+ if (oauthToken) {
275
+ tokenInput.value = oauthToken;
276
+ } else {
277
+ // 保存されたトークンを自動で読み込み
278
+ tokenInput.value = localStorage.getItem("hf_token") || "";
279
+ }
280
+
281
+ tokenInput.addEventListener("input", () => {
282
+ localStorage.setItem("hf_token", tokenInput.value);
283
+ });
284
+ });
285
+ </script>
286
+ </body>
287
+ </html>
288
+ ''', token=token)
289
+
290
+ if __name__ == "__main__":
291
+ app.run(host="0.0.0.0", port=7860)